三和算法解决方案

时间:2017-09-06 04:08:55

标签: python algorithm

原始问题陈述:

给定n个整数的数组S,S中是否有元素a,b,c,a + b + c = 0?找到数组中所有唯一的三元组,它们总和为零。

注意:解决方案集不得包含重复的三元组。

For example, given array S = [-1, 0, 1, 2, -1, -4],

A solution set is: [[-1, 0, 1], [-1, -1, 2]]

你好我在一段时间后解决了LeetCode上的Two Sum问题,我想用它来解决三个和。我的想法是,对于每个元素,在剩余列表中找到两个元素,它们总结为元素* -1得到0.但是,此代码并未通过所有测试,例如

Input: [-4,-2,-2,-2,0,1,2,2,2,3,3,4,4,6,6]
Output: [[-4,-2,6],[-4,0,4],[-4,1,3],[-4,2,2]]
Expected: [[-4,-2,6],[-4,0,4],[-4,1,3],[-4,2,2],[-2,-2,4],[-2,0,2]]

我真的不知道出了什么问题。有人可以善待我解释这个问题。 谢谢

class Solution(object):
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        def twoSum(self, nums, target):
            targ = target
            for index, i in enumerate(nums):
                targ -= i
                if targ in nums[index+1:]:
                    return [nums[index], nums[nums[index+1:].index(targ)+index+1]]
                else:
                    targ = target
            return None
        res = []
        for index, i in enumerate(nums):
            target = i * -1
            num = nums[:index] + nums [index+1:]
            ans = twoSum(self, num, target)
            if ans != None:
                temp = ans + [i]
                temp.sort()
                res.append(temp)
        print(res)
        import itertools
        res.sort()
        res = list(res for res,_ in itertools.groupby(res))
        return res

原始问题:https://leetcode.com/problems/3sum/description/

我用来解决这个问题的人:https://leetcode.com/problems/two-sum/description/

4 个答案:

答案 0 :(得分:5)

使用itertools

import itertools
stuff = [-1, 0, 1, 2, -1, -4]
stuff.sort()
ls = []
for subset in itertools.combinations(stuff, 3):
    if sum(list(subset))==0:
        # first I have sorted the list because of grouping
        # Ex: [-1, 0, 1] and [0, 1, -1] are build with the same element
        # so here is avoiding this.
        if list(subset) not in ls:
            ls.append(list(subset))
print(ls)

<强>输入/输出

input : [-1, 0, 1, 2, -1, -4]
output : [[-1, -1, 2], [-1, 0, 1]]
input : [-4,-2,-2,-2,0,1,2,2,2,3,3,4,4,6,6] 
output: [[-4, -2, 6], [-4, 0, 4], [-4, 1, 3], [-4, 2, 2], [-2, -2, 4], [-2, 0, 2]]

答案 1 :(得分:3)

这是解决它的另一种方法,它具有 O(n ^ 2)时间复杂度并通过LeetCode测试。它会对事件进行计数,然后对(number, count)个元组进行排序,以便[-1, 0, 1, 2, -1, -4]变为[(-4, 1), (-1, 2), (0, 1), (1, 1), (2, 1)]。然后它从开始挑选开始迭代,首先尝试选择每个数字两次,如果可能的话,再增加第三个,并将其添加到结果中。然后它选择一次数字,并试图找到两个更大的数字,总和为0.

from collections import Counter

class Solution(object):
    def threeSum(self, nums):
        res = []
        counts = Counter(nums)
        num_counts = sorted(counts.items())

        # Handle the only case where we pick three same nums
        if counts[0] >= 3:
            res.append([0] * 3)

        for i, (first, first_count) in enumerate(num_counts):
            # Pick two of these and one greater
            if first_count >= 2 and first < 0 and -(first * 2) in counts:
                res.append([first, first, -(first * 2)])

            # Pick one and two greater
            for j in range(i + 1, len(num_counts)):
                second, second_count = num_counts[j]
                # Pick two of these as second and third num
                if second_count >= 2 and -first == 2 * second:
                    res.append([first, second, second])

                # Pick this as second num and third which is greater
                third = -(first + second)
                if third > second and third in counts:
                    res.append([first, second, third])

        return res

答案 2 :(得分:0)

我想在评论中添加您要求的答案:

class Solution(object):
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        def twoSum(self, nums, target):
            targ = target
            for index, i in enumerate(nums):
                targ -= i

                # if targ in nums[index+1:]:
                #    return [nums[index], nums[nums[index+1:].index(targ)+index+1]]
                _num = nums[:index] + nums[index+1:]
                if targ in _num: 
                    return [i, targ]
                else:
                    targ = target
            return None
        res = []
        for index, i in enumerate(nums):
            target = i * -1
            num = nums[:index] + nums [index+1:]
            ans = twoSum(self, num, target)
            if ans != None:
                temp = ans + [i]
                temp.sort()
                res.append(temp)
        print(res)
        import itertools
        res.sort()
        res = list(res for res,_ in itertools.groupby(res))
        return res

我只动了脑筋,希望它是对的。

答案 3 :(得分:0)

一种方法是使用HashSet,我在这里尝试过:

public List<List<Integer>> threeSum(int[] nums) {
        Set<List<Integer>> set = new HashSet<>();
        Arrays.sort(nums);
        for (int i = 0; i < nums.length - 1; i++) {
            int j = i + 1;
            int k = nums.length - 1;
            while (j < k) {
                int sum = nums[i] + nums[j] + nums[k];
                if (sum == 0) {
                    set.add(Arrays.asList(nums[i], nums[j++], nums[k--]));
                } else if (sum > 0) {
                    k--;
                } else if (sum < 0) {
                    j++;
                }
            }
        }
        return new ArrayList<>(set);
    }
}