1. Topic description

Given two ordered (increasing) integer arrays nums1 and nums2 , please return the intersection of the two arrays in array form, M is a longer length array , N is the shorter array length. E.g:
Given: nums1 = [1,2,3,4,5,6] , nums2 = [1,2,3]
Output: [1,2,3]
This problem is common and not difficult. The interesting thing is that there are many solutions. In the scenarios of nums1 and nums2 , choose the most efficient solution.

2. Hash table

This is the easiest solution to think of, hash the shorter array and traverse the longer array to get the intersection

 function intersect(nums1, nums2){
    let hash = new Set()//这里用set来代表哈希,他们本质是一样的
    for (let i = 0; i < nums2.length; i++) {
        hash.add(nums2[i])
    }
    for (let i = 0; i < nums1.length; i++) {
        if (hash.has(nums1[i])) {
            ans.push(nums1[i])
        }
    }
    return ans
}

Time complexity: O(M+N) <br/>
Space complexity: hashed for shorter arrays, O(N)

3. Binary search

Thinking about a scenario, the long array is very long, and the solution of the hash table is linear. Obviously, the condition of the array order is not well utilized. At this time, the binary search stands out, because the greater the difference between the two lengths, the higher the binary efficiency. ;

 function intersect(nums1, nums2){
    //由于是递增,定义一个left,稍微减少下查找范围
    let left = 0;
    for (let i = 0; i < nums2.length; i++) {
                
        //二分查找
        let index = binarySearch(nums1, nums2[i], left)
        if (index != -1) {
            ans.push(nums2[i])
            left = index + 1
        }
    }    
    return ans
}

function binarySearch(nums, target, left  = 0, right = nums.length - 1){
        //特殊处理 端点的情况 可以加速连续数组的查找
        if(nums[left] == target){
            return left
        }
        if(nums[right] == target){
            return right
        }
    while(left <= right){
        mid =  Math.floor((left + right)/2)
        if (nums[mid] == target) {
            return mid
        }else if(nums[mid] > target){
            right = mid - 1
        }else{
            left = mid + 1
        }
    }
    return -1
}
Here we focus on why we should optimize the left starting point of binary search. If we do not give the left starting point, then each binary point is from 0 to len -1 binary, and because the array has In order, if you have found num1 in target , then the next one to be found target must be located in the previous target of 95ebcd7---4ac3599 to the right, thus avoiding the binary search every time from 0 began, under the best circumstances such as nums1 = [1,2,3,4,5,6] , nums2 = [4,5,6] , first find 4 remaining 5 , 6 apparently 4 the right, as long as the actual O(N) times to be a time complexity: M for longer array length, N for shorter array length, worst/average complexity O(N*logM) , and since we optimized the left starting point for binary search , in the most ideal case the complexity can reach O(N) ; not ideally, the time complexity depends on the distribution of the intersection in nums1 , the intersection in nums1 The more right the middle is distributed, the higher the search efficiency is<br/>
Space complexity: if the recursive array is a reference, we only use constant-level variable space O(1)

4. Double pointer

If the lengths of the two arrays are not much different, then double pointers are obviously more efficient;

 function intersect(nums1, nums2){
    let m = n = 0
    while( m < nums1.length && n < nums2.length ) {
        if (nums1[m] == nums2[n]) {
            ans.push(nums1[m])
            m++
            n++
        }else if (nums1[m] > nums2[n]) {
            n++
        }else{
            m++
        }
    }
    return ans
}

Time complexity: M is longer array length, N is shorter array length, the best case is O(N) , the worst case is O(M) <br/>
Space complexity: only constant-level variable space is used O(1)


tfzh
231 声望17 粉丝

code what u love & love what u code


引用和评论

0 条评论