Daily supplementary record 5

Posted by labourstart on Sat, 12 Feb 2022 01:50:39 +0100

2.7

​​​​​​1405. Longest happy string

If the string does not contain any strings such as' aaa ',' bbb 'or' ccc 'as substrings, the string is a "happy string".

Here are three integers a, b and c. please return any string s that meets all the following conditions:

s is a happy string as long as possible.
There are at most a letters' a ', b letters' b', and c letters' c 'in s.
s contains only 'a', 'b' and 'c'.
If such a string s does not exist, return an empty string ''.

Method: greedy and simple. Select the letters with the largest number of remaining letters each time. If there are two consecutive letters, select the letter with the largest number in the remaining two until two remaining numbers are zero. You can't expand any more and return the answer.

Method 1: use the array to maintain the number of letters with the maximum number of remaining letters / times

class Solution {
    public String longestDiverseString(int a, int b, int c) {
        // Construct an array to record the remaining number of each letter
        //Note that the array is int and the ASCII code corresponding to char is saved
        int[][] pairs = {{'a', a}, {'b', b}, {'c', c}};
        //The maximum capacity is a+b+c. It doesn't matter if it's not enough
        StringBuilder sb = new StringBuilder(a + b + c);
        while (true) {
            // Sort by quantity from large to small
            Arrays.sort(pairs,(x,y)->y[1]-x[1]);
            int len=sb.length();
            //If the maximum is zero, it can no longer be spliced
            if(pairs[0][1]==0)break;
            //The largest number has been used twice and can't be used anymore
            if(len>=2&&sb.charAt(len-1)==pairs[0][0]&&sb.charAt(len-2)==pairs[0][0]){
                if(pairs[1][1]==0)break;
                sb.append((char)pairs[1][0]);
                pairs[1][1]--;
            }//The largest quantity has not been used twice, and it can be reused
            else{
                sb.append((char)pairs[0][0]);
                pairs[0][1]--;
            }
        }
        return sb.toString();
    }
}

Method 2: using priority queue maintenance is actually equivalent to storing three arrays in the queue, which is used to replace pairs

One difference: if the extracted array [1] = = 0, it will not be listed, which can reduce the maintenance cost

class Solution {
    public String longestDiverseString(int a, int b, int c) {
        // Large top pile, with a large number at the top
        PriorityQueue<int[]> heap = new PriorityQueue<>((x, y) -> y[1] - x[1]);
        // Initialization into the heap. If the initial quantity is zero, it will not be used
        if (a > 0) {
            heap.offer(new int[] {'a', a});
        }
        if (b > 0) {
            heap.offer(new int[] {'b', b});
        }
        if (c > 0) {
            heap.offer(new int[] {'c', c});
        }
        StringBuilder sb = new StringBuilder(a + b + c);
        while (!heap.isEmpty()) {
            //Large root heap, which is the largest number of letters left at present
            int[]max=heap.poll();
            int len=sb.length();
            //The maximum value has been used twice and can no longer be used
            if(len>=2&&sb.charAt(len-1)==max[0]&&sb.charAt(len-2)==max[0]){
                //First of all, make sure that there is still a large value
                if(!heap.isEmpty()){
                    //Take the next largest value
                    int[]mid=heap.poll();
                    sb.append((char)mid[0]);
                    mid[1]--;
                    if(mid[1]>0){
                        heap.offer(mid);
                    }
                    //What is easy to miss is that even if the next largest value is used, the maximum value should also be added to the heap
                    heap.offer(max);
                }else{
                    //If not, return directly
                    break;
                }
            }else{
                sb.append((char)max[0]);
                max[1]--;
                if(max[1]>0){
                    heap.offer(max);
                }
            }
        }
        return sb.toString();
    }
}

 2.8

1001. Grid lighting

On a grid of size n x n, each cell has a light, which is initially turned off.

Give you a two-dimensional array of lights consisting of the positions of lights, where lights [i] = [rowi, coli] means to turn on the lights located in grid[rowi][coli]. Even if the same lamp may be listed multiple times in lamps, it will not affect that the lamp is on.

When a light is on, it will illuminate its own cell and all other cells on the same row, column and two diagonals.

Give you another two-dimensional array queries, where queries[j] = [rowj, colj]. For the j-th query, if the cell [rowj, colj] is illuminated, the query result is 1, otherwise it is 0. After the j-th query [in the order of query], turn off any lights located on cell grid[rowj][colj] and 8 adjacent directions (sharing corners or edges with cell grid[rowi][coli]).

Returns an integer array ans as the answer. ans[j] should be equal to the result of the j-th query. 1 means illuminated and 0 means not illuminated.

The grid size n*n, n can be taken as 10 ^ 9, which obviously will TLE. Therefore, we use the hash table to record the row and column inclination illuminated by each lamp, and use the set to record the position of all lamps. In order to save space, we also need to talk about the transformation of point coordinates from two-dimensional to one-dimensional (i.e. hash transformation)

class Solution {
    int N;
    public int[] gridIllumination(int n, int[][] lamps, int[][] queries) {
        N=n;
        int[][] dirs = new int[][]{{0,0},{0,-1},{0,1},{-1,0},{-1,-1},{-1,1},{1,0},{1,-1},{1,1}};
        Map<Integer,Integer>row=new HashMap<>(),col=new HashMap<>(),
        left=new HashMap<>(),right=new HashMap<>();
        Set<Long>set=new HashSet<>();
        //Record all lights and grids on
        for(int[]l:lamps){
            int x=l[0],y=l[1];
            int a=x+y,b=x-y;
            if(set.contains(hash(x, y)))continue;
            set.add(hash(x, y));
            add(row, x);
            add(col, y);
            add(left, a);
            add(right, b);
        }
        int m=queries.length;
        int[]ans=new int[m];
        //Processing queries
        for(int i=0;i<m;i++){
            int[]q=queries[i];
            int x=q[0],y=q[1];
            int a=x+y,b=x-y;
            //Five lighting modes
            if(set.contains(hash(x, y))||row.containsKey(x)||col.containsKey(y)||left.containsKey(a)||right.containsKey(b)){
                ans[i]=1;
            }
            //If there is a light in the nine palaces, turn it off
            for(int[]dir:dirs){
                int dx=x+dir[0],dy=y+dir[1];
                if (dx < 0 || dx >= n || dy < 0 || dy >= n) continue;
                if(set.contains(hash(dx, dy))){
                    set.remove(hash(dx, dy));
                    minus(row, dx);
                    minus(col, dy);
                    minus(left, dx+dy);
                    minus(right, dx-dy);
                }
            }
        }
        return ans;
    }
    //From two-dimensional to one-dimensional, all points are represented and stored with a Long data
    long hash(int x,int y){
        return x*N+y;
    }
    void add(Map<Integer,Integer>map,int key){
        map.put(key, map.getOrDefault(key, 0)+1);
    }
    void minus(Map<Integer,Integer>map,int key){
        if (map.get(key) == 1) map.remove(key);
        else map.put(key, map.get(key) - 1);
    }
}

2.9

2006. Number of pairs whose absolute value of difference is K

Give you an integer array | nums | and an integer | k. please return the number of number pairs (i, j), satisfying | I < J | and | nums[i] - nums[j]| == k.

|The value of | is defined as:

If , x > = 0, the value is , X.
If x < 0, the value is - X.

This question is very similar to the sum of two numbers in the first question. Naturally, there are two ways!

Method 1: Double traversal

class Solution {
    public int countKDifference(int[] nums, int k) {
        int ans=0,n=nums.length;
        for(int i=0;i<n;i++){
            for(int j=i+1;j<n;j++){
                if(Math.abs(nums[i]-nums[j])==k)ans++;
            }
        }
        return ans;
    }
}

Hash table: Method 2

class Solution {
    public int countKDifference(int[] nums, int k) {
        int ans=0,n=nums.length;
        HashMap<Integer,Integer>map=new HashMap<>();
        for(int i=0;i<n;i++){
            map.put(nums[i],map.getOrDefault(nums[i],0)+1);
            ans+=map.getOrDefault(nums[i]-k,0)+map.getOrDefault(nums[i]+k,0);
        }
        return ans;
    }
}

Topics: Algorithm greedy algorithm