[leetcode 3sum】 三数之和问题 @python

原题

这里写图片描述

题目大意

给定一个包含 n 个整数的数组,问是否存在属于数组的三个元素 a、b、c,使得 a+b+c = 0,并返回所有的 [a,b,c] 取值情况(要剔除重复的取值情况)

解题思路

第一反应是进行遍历,穷举出数组中三个元素的所有组合情况,再筛选出符合条件的,但这个要三重循环,时间复杂度太高,放弃。

我的思路是将其转化为 n-2 个 2sum 问题来实现;具体思路如下:假设 数组为 [A1,A2,A3,A4,……An],首先对数组从 A1 到 An-2 进行遍历,取值为Ai,再从剩下的 n-i 个元素中找到两个元素 M、N,使其满足 M+N = -Ai,这样就相当于找到了,三个元素满足 Ai + M + N = 0

至于 2sum 的问题,我们可以先将数组排序,然后分设两个指针,从两端向中间逼近,具体实现看代码。

这个方法有个比较绕的地方(咱也捋了好一会,才捋明白)就是为什么是从 n-i 个元素中找 M、N,而不是从 n-1个元素中。咱举个栗子,假设 Ai 取值为 A4 的时候,按照之前的说法,就应该是从 A5 到 An 中查找剩下的 M、N。有些人可能会说,还漏了 A1 到 A3 啊,其实不然,如果 M 或 N 取 A1 到 A3 中的某个值的话就会和之前的情况重叠。比如说 M 取值为 A2 ,N 去任意值,那么这个时候三个元素的取值分别是 [Ai = A4,M = A2,N = N] 这个和[Ai = A2,M = A4,N = N] 的情况重复了,不需要考虑。

还有一个比较麻烦的问题就是去重,我的解决方法是,每次处理完一种情况后,如果发现接下来的这个数和上一个数是相同的(数组已经排序了),则跳过这个相同的数值,因为多个相同的数值分别和任意两个数,组合出来的三元组都是一样的,所以只考虑一次即可。

代码实现

class Solution:
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        res = []
        lent = nums.__len__()
        nums.sort() # 对数组进行排序
        i = 0
        while i < lent-2: # 这个临界值要考虑清楚,因为是三个元素,第一个元素只需要取到倒数第三个数就成
            left = i + 1 # 从左边找小的
            right = lent-1 # 从右边找大的
            while left<right:
                if nums[left]+nums[right] == -nums[i]:
                    res.append([nums[i],nums[left],nums[right]])
                    # 相同的元素和任意两个元素的组合情况都是一样的,考虑一个即可
                    while left < lent-1 and nums[left] == nums[left+1]:
                        left = left + 1
                    while right > 0 and nums[right] == nums[right-1]:
                        right = right -1
                    left = left + 1
                    right = right -1
                # 三个元素之和大于 0 ,将 right 往左移一位,取小一点的    
                elif nums[left]+nums[right] > -nums[i]:
                    right = right -1
                # 三个元素之和小于 0 ,将 left 往右移一位,取大一点的
                else:
                    left = left + 1
            # 和上面的一样,相同元素只考虑一个即可
            while i < lent-2 and nums[i] == nums[i+1]:
                i = i + 1
            i = i + 1
        return res

和这道类似的题目还有最接近的三数之和四数相加 ,方法都差不多,理解了的朋友可以用这两道,练练手。

猜你喜欢

转载自blog.csdn.net/slwhy/article/details/79854277