Common problem solving methods (bit operation, double pointer, prefix and)

Keywords: Java Algorithm quick sort


This paper summarizes some common simple problem-solving methods encountered in the process of brushing questions:

Array is a kind of linear table in data structure. It is often displayed in the form of integer array and string in algorithm problems. In fact, the array contains more data types. This paragraph mainly explains the solutions to some common problems of integer array;

A feature of array is that it can quickly access data through subscript, that is, a[i] = xx;

Bit operation

In essence, it should be counted in a large class of algorithms in the Department of mathematics. The final result is obtained by performing a bit operation on each number in the array.
A series of operations after the bit operation index is transformed into binary, such as and, or, non, same or, XOR, shift left and shift right, etc. through these operations, an efficient algorithm is achieved;
It is common to use some of its characteristics to solve problems: such as bit processing of left-right shift; The two operands of the XOR result are the same as 0 and the difference is 1;
Illustrate with some examples:
1,leetcode29 divide two numbers

This problem requires the division of two numbers; Division, title and remainder are not allowed;

Solution: analyze the problem directly from the result. You need to get division and hypothetical calculation A/B,Division is essentially a number A Contains less than B;
Then an intuitive solution is to use the subtraction loop A=A-B This form, until it can no longer be reduced; For example, 10/3;It can be reduced three times to the third time A Equal to 1, no more subtraction; Three cycles in total, so the result is 3;
Pseudo code:
Accept two parameters A\B,Divisor and dividend
define count = 0;Counter;
while(A greater than B){
        A-B,;Counter plus 1;
}
Return counter;
(The cross-border situation is not considered here, only the algorithm is explained)

This algorithm obviously needs to be optimized. The optimization method is to reduce the multiple of B every time and try to remember the counter several times at a time; For example, 13 / 3; Try 13 / (3 + 3 + 3 + 3) = 1; The actual result should be the addition of these four three; Multiplication cannot be used; Therefore, the left shift can be used here, that is, 3 < < 4; The results can be obtained directly without adding; Therefore, you can use the high position to move down slowly until you find the result;
Pseudo code:

Accept parameters A and B;
define Counter
for(i=31 to i=0){
If B Shift left i The result of times is greater than A;Then the counter is equal to this value;
}
return Counter

2,Leetcode 137 is a number that appears only once
This problem means that only one number in an array appears once and the others appear three times; Find this number. For example, the result of [2,2,1,2,3,3,3] is 1;

Solution: in the binary form of numbers, for numbers that appear three times, the number of binary bits is a multiple of 3.
Therefore, the number of occurrences of 1 in each binary bit of all numbers is counted, and the remainder of 3 is calculated, and the result is a number that occurs only once.
For example [1,1,1,3];Each binary bit of each number is added up, and then the remainder is 3. The result should be 011, that is, 3;
      //Loop 32 times, int has 32 bits
        for(int i = 0;i<32;i++){
            int sum = 0;
            for(Traverses the number of in the array n){
                //For each number in the array, shift i bits to and 1 each time; That is, take out the value in bit i;
                sum += (n>>i)&1;
            }
            //Sum and remainder the numbers on each binary bit to obtain the value on the ith bit of the final result; In homing;
            sum%=3;
            ans+=sum<<i;
        }
        return ans;
    }

3,leetcode318 find the maximum word length
Given a string array words, find the maximum value of length(word[i]) * length(word[j]), and the two words do not contain common letters. You can think that each word contains only lowercase letters. If there are no such two words, 0 is returned.
That is, the longest result of two words in the array that do not contain duplicate letters at all;

	Solution: different words contain different letters. You can directly think of establishing a dictionary for each word to record their letters; Therefore, binary can be used to identify the occurrence of their letters“ ac"Marked 101; and“ ad"The identification is 1001“ abc"Expressed as 111; so that each word can be expressed; finally, compare the binary bits when traversing the array;
Identification process:
Define record array;
for(Traverse the entire array){
    for(Traverse the string array at this location){
             with ascll Table as an example, use the record array record 1 to shift right and subtract each character code a The number of coded digits on the position;
    }
}
Detection process
for(Traversal record array){
      for(Traverses the record array after the current subscript){
             Compare whether the binary system bits on the words are the same; if they are the same, record the maximum value;
      }
}

Double pointer

In a broad sense, double pointers refer to the problem solved by traversing two variables in a linear structure. In an array, they can move in the same direction or in both directions; in a linked list, two pointers move in the same direction, but the speed can be different, which is generally called fast and slow pointers;
Some common application scenarios of double pointers: sliding window, sorting, binary search, etc;
Classification: same direction pointer: speed and interval pointer; different direction pointer: collision;
Problems needing attention during use: pointer pointing, moving direction, starting position, when to move and moving speed;
1. Application of collision pointer;
Collision pointer generally refers to two pointers moving in different directions, such as one moving from head to tail and one moving from tail to head; a typical collision pointer application is the binary search algorithm; the general use of binary search is as follows

Define left pointer = 0;
Right pointer equals length - 1;
while(The left pointer is smaller than the right pointer){
             Program operation;
             if(condition){
             	Left++;
             }
             if((condition){
				right--;
			}
             
}

Examples
lc15 sum of three numbers
For an array, find the triples [a, b, c] in the array so that a+b+c=0;
Solution: the essence of this problem is a search algorithm; if we know "a", find "-" (b+c) "in the array;
Use sort Plus + collision pointer to do

  Array sorting
 Find results

   Define the result set;
    for (From the first number to the penultimate number) {
        if(i!=0&&nums[i]==nums[i-1]) continue;
       Define the left and right pointers. The left pointer is equal to the of the outer loop i,The right pointer is the end of the array;
       while(left<right){
             Skip duplicate values; prevent duplicate results from being recorded;
            
            Record the sum of the numbers at the left and right pointers sum;
            
           
           if(If sum Exactly equal to the current number of outer loops a Opposite number of){
                          Record the left and right pointer results, and move the left and right pointers to the place where the values are not repeated;
           
           }else if( The sum of the left and right pointers is smaller than the opposite of the value of the outer loop){
                          Left pointer movement eft++;
           
           }else{ //This sum is greater than the opposite of the value of the outer loop;
                           Right pointer movement right--;
           }
       }
    }
Finally, return the result set;

2. The speed pointer in the same direction; the left and right pointers move from one side to the other; the classic case is whether there are links in the linked list;
Through two pointers with inconsistent speed, one moves together from front to back until the pointers coincide;
code:

public boolean hasCycle(ListNode head) {
    ListNode slow = head;
          ListNode fast = head;
    while (slow != null && fast != null) {
                 ListNode n = fast.next;
     fast = n == null ? null : n.next;
     if (slow == fast) {
         return true;
     }
                 slow = slow.next;
    }
    return false;
    }

3. Same direction interval pointer; similar to sliding window, one pointer is in front and one pointer is behind, which moves synchronously or asynchronously to solve some problems; that is, define a left pointer to move on the left and the right pointer to move behind;
lc 3 longest string without duplicate characters
Judge the longest string without characters in the string;

Solution: it is solved by moving the sliding window. The left pointer does not move, and the right pointer moves forward; When the right pointer moves to the repeated character, pull the left pointer to the right pointer and record the maximum value;

public int lengthOfLongestSubstring(String s) {
        if (s.length()==0) return 0;
        HashMap<Character, Integer> map = new HashMap<Character, Integer>();
        int max = 0;
        int left = 0;
        for(int i = 0; i < s.length(); i ++){
            if(map.containsKey(s.charAt(i))){
                left = Math.max(left,map.get(s.charAt(i)) + 1);
            }
            map.put(s.charAt(i),i);
            max = Math.max(max,i-left+1);
        }
        return max;
        
    }

Prefix and

The result is obtained by preprocessing the array. The prefix sum refers to the sum of the first n items of the record array; For example, array [1,2,3,4], that is, store the results [1,3,6,10] in the new array; Through such an array to solve some problems;
It is easy to find the n-term sum of subarrays through prefix sum, and many summation problems can be solved through the sum of subarrays, such as finding the middle number of the array so that the front sum is equal to the rear sum, or the subarray whose sum is greater than a certain number, etc; Using this idea, we can also solve the problems related to product;
lc560 and subarray with k
Give you an integer array nums and an integer k. please count and return the number of consecutive sub arrays in the array and k.

public int subarraySum(int[] nums, int k) {
        int count = 0;
        //For prefix sum, the hash table is used to record the prefix sum. If sum-k exists in subsequent traversal, that is, the current prefix and - k = the previous prefix sum, it means that the sum from this position to the present position is equal to K
        HashMap<Integer,Integer> map = new HashMap<>();
        map.put(0,1);
        int sum = 0;
        for(int i = 0;i<nums.length;i++){
            sum+=nums[i];
            count+=map.getOrDefault(sum-k,0);
            map.put(sum,map.getOrDefault(sum,0)+1);
        }
        return count;
    }

lc continuous 01 subarray

Differential array
Similar to prefix and, differential array refers to the new array obtained by differential operation on the original array, that is, the new array from [1,2,3,4] is [1, - 1, - 2, - 3]; It can also solve many similar problems;

Posted by zoozle on Tue, 23 Nov 2021 05:43:37 -0800