Original title address: https://leetcode-cn.com/problems/intersection-of-two-arrays-ii/description/given two arrays, write a method to calculate their intersection.
For example:
Given nums1 = [1, 2, 2, 1], nums2 = [2, 2], return [2, 2].
Attention:
- The number of occurrences of each element in the output should coincide with the number of occurrences of the element in two arrays.
- We can not consider the order of the output results.
Follow:
- What if the given array is already sorted? How will you optimize your algorithm?
- If the size of the nums1 is much smaller than the nums2 , which method is better?
- If the nums2 element is stored on disk, the memory is limited, you cannot load all the elements into memory at once, what should you do?
Above is the original question we first to solve the problem in accordance with conventional ideas, and then gradually analyze the final concentration of special circumstances. Idea: 1. Add a counter to record the number of occurrences of one of the array elements. 2. Iterate over another array, if the array element has records in the counter and the number of records is greater than 1, the number is added to the result array, and the number of times the counter is recorded is reduced by 1. The implementation code is as follows:
1 Public int[] Intersect (int[] nums1,int[] nums2) {2Map<integer, integer> counter =NewHashmap<> ();//counter, key is the number in the array, and value is the number of occurrences of the number3 for(inti = 0; i < nums1.length; i++) {4 intnum =Nums1[i];5 if(Counter.containskey (num)) {6Counter.put (num, counter.get (num) + 1);7}Else {8Counter.put (NUM, 1);9 }Ten } OneList<integer> templist =NewArraylist<>(); A for(inti = 0; i < nums2.length; i++) { - intnum =Nums2[i]; - if(Counter.containskey (num) && counter.get (num) > 0) { theCounter.put (num, counter.get (num)-1);//Number of times the number is recorded in the counter minus 1 -Templist.add (num);//Add this number to the list - } - } + int[] result =New int[Templist.size ()]; - //To satisfy the problem return value type, convert the list to an int array + for(inti = 0; i < result.length; i++) { AResult[i] =Templist.get (i); at } - returnresult; -}
OK, the basic function has been realized, next we think together how to meet several follow-up issues:
- What if the given array is already sorted? How will you optimize your algorithm?
Idea: Since two arrays are ordered, we can scan two arrays sequentially with two pointers C1 and C2, respectively, to get two numbers m and N, with the following three relationships:
1, M = = N, the number is a repeating number, the number is added to the result array, and two pointers are shifted one after the other.
2, M > N, we need to move the C2 pointer back one bit.
3, M < n, we need to move the C1 pointer back one bit.
Repeat the above steps until C1 or C2 one of the pointers has been moved to the end of the array.
The code is implemented as follows:
1 Public int[] Intersect (int[] nums1,int[] nums2) {2 intCur1 = 0, cur2 = 0;//define pointer, point to array start position3list<integer> list =NewArraylist<>();4 while(Cur1 < Nums1.length && CUR2 < nums2.length) {//Loop End Condition: Any one pointer points to the end of the corresponding array5 intNUM1 =Nums1[cur1];6 intnum2 =NUMS2[CUR2];7 if(NUM1 = = num2) {//repeating numbers, joining the results list8 List.add (NUM1);9cur1++;Tencur2++; One}Else if(Num1 < NUM2) {//move the Cur1 pointer back one bit to continue the next comparison Acur1++; -}Else{//move the CUR2 pointer back one bit to continue the next comparison -cur2++; the } - } - int[] result =New int[List.size ()]; - // To satisfy the problem return value type, convert the list to an int array + for(inti = 0; I < list.size (); i++) { -Result[i] =List.get (i); + } A returnresult; at}
- If the size of the nums1 is much smaller than the nums2 , which method is better?
Let's compare these two methods: assuming that the length of nums1 and Nums2 is L1, L2. The first: The loop that does not consider the end conversion int array, a total of two loops: 1, the first cycle of the NUMS1 initialization counter. 2. The second cycle NUMS2 is compared with the values stored in the counter.in any case, both of these loops need to be fully executed, with the actual number of cycles L1 + L2. The second type: The loop that does not consider the end conversion int array, there is a total of a loop: 1, each cycle in nums1 and NUMS2 in the comparison of values, if equal, while moving two pointers, a pointer ends, the loop ends. Because the L1 is much smaller than the L2, only need to perform the L1 cycle, the actual consumption of time is much smaller than the first method.worst-case scenario:The worst case scenario is that there is no duplicate number in nums1 and NUMS2, and the last element in NUMS1 is greater than the penultimate element of NUMS2, and the last element of NUMS2 is greater than the penultimate element of NUMS1, in which case the loop of the second method also needs to be executed L1 + L2 times. Therefore, only in extreme cases, the efficiency of the two methods is approximately equal, and in any other case, the second method is preferable to the first method.
- If the nums2 element is stored on disk, the memory is limited, you cannot load all the elements into memory at once, what should you do?
If the NUMS2 elements are too many to be loaded into memory at once, then we should:
1, the number in the NUMS1 initialization counter.
2, using the buffer stream to read a portion of the file data, the counter has a record and the number of records more than 1, the number is added to the result array, the number of times in the counter record is reduced by 1, thus completing the statistics of this part of the data.
3, then read the next part of the file data, repeat step 2.
OK, the above is the question of some ideas, if friends have a better way, welcome message exchange HA ~
Intersection of two arrays II [LeetCode-350]