[LeetCode]350. Intersection of Two Arrays II

350. Intersection of Two Arrays II

题目:和前面不一样的是,它允许出现多个次数。

Counter

利用两个Counter来进行统计,需要注意的是,需要取两个Counter中个数的较小值,时间复杂度为O(min(m, n))

import collections
class Solution(object):
    def intersect(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: List[int]
        """
        res = []
        counter1 = collections.Counter(nums1)
        counter2 = collections.Counter(nums2)
        if len(counter2) < len(counter1):
            counter1, counter2 = counter2, counter1
        for key, val in counter1.items():
            if key in counter2:
                res.extend([key] * min(val, counter2[key]))
        return res

看了别人的做法,才记起来Counter中有&操作,也就是取相对应的键的最小值。如下:

def intersect(self, nums1, nums2):
    a, b = map(collections.Counter, (nums1, nums2))
    return list((a & b).elements())

Two Pointers

分别维护两个数组的起始结点的指针,如果相等则向右移动,需要注意的是,如果不相等时,则让当前小的值向右移动。时间复杂度为O(m+n)。

class Solution(object):
    def intersect(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: List[int]
        """
        res = []
        sorted_nums1 = sorted(nums1)
        sorted_nums2 = sorted(nums2)
        if len(sorted_nums2) > len(sorted_nums1):
            sorted_nums1, sorted_nums2 = sorted_nums2, sorted_nums1
        i, j = 0, 0
        while i < len(sorted_nums1) and j < len(sorted_nums2):
            if sorted_nums1[i] == sorted_nums2[j]:
                while i < len(sorted_nums1) and j < len(sorted_nums2) and sorted_nums1[i] == sorted_nums2[j]:
                    res.append(sorted_nums1[i])
                    i += 1
                    j += 1
            else:
                if sorted_nums1[i] < sorted_nums2[j]:
                    while i < len(sorted_nums1) and sorted_nums1[i] < sorted_nums2[j]:
                        i += 1
                    if i == len(sorted_nums1):
                        break
                else:
                    while j < len(sorted_nums2) and sorted_nums2[j] < sorted_nums1[i]:
                        j += 1
                    if j == len(sorted_nums2):
                        break
        return res

二分查找

我们还可以使用二分查找优化之前的代码,需要注意的是,如果相等的时候,需要定位到右边的位置,因为要找出尽可能多的相同元素,而不想等的时候,需要定位到左边的位置,因为不想等的值可能会存在多个。

class Solution(object):
    def intersect(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: List[int]
        """
        # 找到最右边的值
        def findRight(nums, start, x):
            i, j = start, len(nums)
            while i < j:
                mid = (i + j) // 2
                if x < nums[mid]:
                    j = mid
                else:
                    i = mid + 1
            return i
        # 找到最左边的值
        def findLeft(nums, start, x):
            i, j = start, len(nums)
            while i < j:
                mid = (i + j) // 2
                if x > nums[mid]:
                    i = mid + 1
                else:
                    j = mid
            return i
        res = []
        sorted_nums1 = sorted(nums1)
        sorted_nums2 = sorted(nums2)
        i, j = 0, 0
        while i < len(sorted_nums1) and j < len(sorted_nums2):
            if sorted_nums1[i] == sorted_nums2[j]:
                end_i = findRight(sorted_nums1, i, sorted_nums1[i])
                end_j = findRight(sorted_nums2, j, sorted_nums1[i])
                res.extend([sorted_nums1[i]] * min(end_i - i, end_j - j))
                i = end_i
                j = end_j
            else:
                if sorted_nums1[i] < sorted_nums2[j]:
                    i = findLeft(sorted_nums1, i, sorted_nums2[j])
                else:
                    j = findLeft(sorted_nums2, j, sorted_nums1[i])
        return res
posted @ 2017-09-03 12:45  banananana  阅读(181)  评论(0编辑  收藏  举报