LeetCode 2sum/3sum/4sum

题目

nSUM问题是指,在一个数组中,找出n个数相加和等于给定的数,返回数的下标列表。

2sum

字典法

建立 {元素:下标} 字典,遍历数组,判断target-x是否在字典里,如果在则返回结果,如果不在字典里就把当前元素加入字典。不在一开始遍历数组建字典,为了避免重复元素抵消下标,比如[2,2],只能存一个下标。
时间复杂度为O(n)

class Solution:
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        hashmap = {}
        for i, x in enumerate(nums):
            y = target - x
            if y in hashmap:
                return hashmap[y],i
            hashmap[x]=i

排序,对撞指针

使用两个指针一个在头一个在尾,将收尾相加求和与target比较,因为有序,如果大于target就把i 右移 ,如果小于就把j 左移。
时间复杂度是O(nlogn),主要在于排序的时间

    def twoSum1(self, numbers, target):
        """
        :type numbers: List[int]
        :type target: int
        :rtype: List[int]
        """
        l = len(numbers)
        i, j = 0, l-1
        while i < j:
            if numbers[i] + numbers[j] == target:
                return i, j
            elif numbers[i] + numbers[j] > target:
                j -= 1
            else:
                i += 1

3sum

对于排序后的数组遍历,对每个位置都从它的后一个元素和末尾一个元素向中间集中,如果和为0就添加到结果数组中。这里需要注意的地方是需要跳过相同的数字,因为同样的数字组合只能出现一次。
时间复杂度是O(N^2),空间复杂度是O(1)

class Solution(object):
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        N = len(nums)
        nums.sort()
        res = []
        for t in range(N - 2):
            if t > 0 and nums[t] == nums[t - 1]:#和前一个数相等,跳过
                    continue
            i, j = t + 1, N - 1
            while i < j:
                _sum = nums[t] + nums[i] + nums[j]
                if _sum == 0:
                    res.append([nums[t], nums[i], nums[j]])
                    i += 1
                    j -= 1
                    while i < j and nums[i] == nums[i - 1]:#和前一个数相等,跳过
                        i += 1
                    while i < j and nums[j] == nums[j + 1]:#和后一个数相等,跳过
                        j -= 1
                elif _sum < 0:
                    i += 1
                else:
                    j -= 1
        return res

另一种思路是,最外层遍历一遍,等于选出一个数, 之后的数组中转化为找和为target-nums[i]的2SUM问题,调用2sum函数。

4sum

总结一下K-sum题目。

  1. 首先先排序
  2. 然后用K - 2个指针做O(N^(K - 2))的遍历
  3. 剩下2个指针从第2步的剩余区间里面找,找的方式是使用两个指针p, q分别指向剩余区间的首尾,判断两个指针的和与target - 第2步的和的关系,对应的移动指针。即如果两个数的和大了,那么,q–;如果两个数的和小了,那么,p++;等于的话,输出结果。要时刻注意p < q.
  4. 用p,q查找剩余区间结束之后,需要移动前面的K-2个值,这里需要在移动的过程中做个去重,找到和前面不同的值继续查找剩余区间。

时间复杂度是O(N^3),空间复杂度是O(1).

class Solution(object):
    def fourSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[List[int]]
        """
        N = len(nums)
        nums.sort()
        res = []
        i = 0
        while i < N - 3:
            j = i + 1
            while j < N - 2:
                k = j + 1
                l = N - 1
                remain = target - nums[i] - nums[j]
                while k < l:
                    if nums[k] + nums[l] > remain:
                        l -= 1
                    elif nums[k] + nums[l] < remain:
                        k += 1
                    else:
                        res.append([nums[i], nums[j], nums[k], nums[l]])
                        while k < l and nums[k] == nums[k + 1]:
                            k += 1
                        while k < l and nums[l] == nums[l - 1]:
                            l -= 1
                        k += 1
                        l -= 1
                while j < N - 2 and nums[j] == nums[j + 1]:
                    j += 1
                j += 1 # 重要
            while i < N - 3 and nums[i] == nums[i + 1]:
                i += 1
            i += 1 # 重要
        return res

参考:https://blog.csdn.net/fuxuemingzhu/article/details/83543296

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值