Title:
Given two arrays, write a function to calculate their intersection.
Given two arrays, write a function to compute their intersection.
Example 1:
Input: nums1 = [1,2,2,1], nums2 = [2,2] Output: [2,2]
Example 2:
Input: nums1 = [4,9,5], nums2 = [9,4,9,8,4] Output: [4,9]
Explain:
- The number of occurrences of each element in the output result should be the same as the number of occurrences of the element in both arrays.
- We can ignore the order of output results.
Note:
- Each element in the result should appear as many times as it shows in both arrays.
- The result can be in any order.
Advance:
- What if the given array is already ordered? How will you optimize your algorithm?
- If the size of nums1 is much smaller than nums2, which method is better?
- If nums2's elements are stored on disk, the disk memory is limited, and you can't load all elements into memory at once, what should you do?
Follow up:
- What if the given array is already sorted? How would you optimize your algorithm?
- What if nums1's size is small compared to nums2's size? Which algorithm is better?
- What if elements of nums2 are stored on disk, and the memory is limited such that you cannot load all elements into the memory at once?
Solutions:
Don't talk about violent problem solving.
-
Hash table:
The frequency of each number in one array is calculated by hash mapping. Traversing another array, each time the same number is encountered, its storage frequency is reduced by one. If the frequency is 0, the hash map is moved out. Such as:
Enter nums1 = [4, 9, 5], nums2 = [9, 4, 9, 8, 4} Calculate nums1 frequency: {4:1, 9:1, 5:1}, key = {4, 9, 5} Traversal nums2: 9 exists in Key, 9 frequency - 1 is 0, 9 moves out of HashMap: {4:1, 5:1} 4 exists in Key, 4 frequency - 1 is 0, 4 moves out of HashMap: {5:1} 9 does not exist in Key, skipping 8 does not exist in Key, skipping ... Output: {9, 4}
-
Double pointer:
First, sort two arrays, define two pointers i, j, move pointer
- If nums1 [i] == nums2 [j], the number is shared.
- If not, move a pointer with a smaller element value.
Such as:
Enter nums1 = [4, 9, 5], nums2 = [9, 4, 9, 8, 4] Sort nums1 = [4, 5, 9], nums2 = [4, 4, 8, 9, 9] Double pointer traversal: [4, 5, 9], [4, 4, 8, 9, 9] ^ ^ 4 = 4, store res = [4], move double pointer: [4, 5, 9], [4, 4, 8, 9, 9] ^ ^ 5 > 4, move pointer to 4: [4, 5, 9], [4, 4, 8, 9, 9] ^ ^ 5 < 8, move pointer to 5: [4, 5, 9], [4, 4, 8, 9, 9] ^ ^ 9 > 8, move pointer to 8: [4, 5, 9], [4, 4, 8, 9, 9] ^ ^ 9 = 9, save res = [4, 9], move double pointer: [4, 5, 9], [4, 4, 8, 9, 9] ^ ^ nums1 length exceeded, end, return res
Answer the advanced questions:
- The main time-consuming operation of double finger method is the sorting algorithm of sorting operation. For an ordered array, of course, use two pointers to solve the problem.
- When the length of an array is far less than that of another array, the hash table is better to solve the problem. It only needs to hash the element frequency of the array with smaller length and traverse the long array. The time complexity depends on the length of the long array. If we use the double finger method, it will take more time to sort the long array.
- If the memory is limited, you can only choose the double finger method or brute force method, without additional space complexity. When using a hash table, in the worst case, each number only appears once. After the HashMap element frequency is counted, its size may be larger than the memory capacity.
Hash table solution:
Java:
class Solution { public int[] intersect(int[] nums1, int[] nums2) { HashMap<Integer, Integer> map = new HashMap<>(); List<Integer> list = new ArrayList<>();//Dynamic array for (Integer num : nums1) map.put(num, map.getOrDefault(num, 0) + 1);//Frequency of statistical elements for (Integer num : nums2) {//Traverse another array if (map.containsKey(num)) { int tmp = map.get(num)-1;//The frequency is reduced by one. if (tmp == 0) map.remove(num);//When the frequency is 0, remove the HashMap else map.put(num, tmp);//Otherwise, update frequency list.add(num);//Add dynamic array } } //Convert to array and return int size=list.size(); int[] res = new int[size]; for (int i = 0; i < size; i++) res[i] = list.get(i); return res; } }
Python:
class Solution: def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]: count = dict(collections.Counter(nums1))# Occurrence frequency of statistical elements in the built-in database and change to Dict type res = [] for num in nums2:# Traverse another array if num in count: count[num] -= 1# Word frequency reduction res.append(num) if count[num] <= 0:# Remove dictionary when word frequency is 0 count.pop(num) return res
Double pointer problem solving:
Java:
class Solution { public int[] intersect(int[] nums1, int[] nums2) { List<Integer> list = new ArrayList<>(); Arrays.sort(nums1);//Sort array Arrays.sort(nums2); int i = 0, j = 0;//Defining pointer while (i < nums1.length && j < nums2.length) { if (nums1[i] < nums2[j]) i++;//Move a pointer with a smaller number else if (nums1[i] > nums2[j]) j++;//Move a pointer with a smaller number else { //If two numbers are equal, it is an intersection, which is stored in a dynamic array and moved by two pointers list.add(nums1[i]); i++; j++; } } //Convert to array and return int[] res = new int[list.size()]; for (int k = 0; k < list.size(); k++) res[k] = list.get(k); return res; } }
Python:
class Solution: def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]: i, j, nums1_size, nums2_size = 0, 0, len(nums1), len(nums2)# Define pointer, calculate array length nums1, nums2, res = sorted(nums1), sorted(nums2), []# Sorting array, initializing return array res while i < nums1_size and j < nums2_size:# Loop condition is pointer does not overflow if nums1[i] < nums2[j]:# Move pointer with smaller value i += 1 elif nums1[i] > nums2[j]:# Move pointer with smaller value j += 1 else: res.append(nums1[i])# If the values are equal, it is an intersection. Move the double pointer i += 1 j += 1 return res
Welcome to wechat.com.com.cn: love to write Bug