[Leetcode] 18. 4Sum

Problem:

Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.

Note: The solution set must not contain duplicate quadruplets.

For example, given array S = [1, 0, -1, 0, -2, 2], and target = 0.

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

Idea:
Just refer to the question about 2Sum and 3Sum. We can simplify this Problem into a N-2 Problem.

Solution:

1. Here is a most straight forward solution specially for the Problem 4Sum.

class Solution(object):
    def fourSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[List[int]]
        """
        lennums = len(nums)
        resultlist = []
        i = j =0 
        nums.sort()
        if lennums < 4:
            return []
        for i in xrange(lennums):
            for j in xrange(i+1,lennums):
                tmpi = i+1
                tmpj = j-1
                while tmpi < tmpj:
                    if tmpi >= lennums or tmpj <= 0:
                        break
                    tmpresult = nums[i]+nums[j]+nums[tmpi]+nums[tmpj]
                    if tmpresult < target:
                        tmpi += 1
                    elif tmpresult > target:
                        tmpj -= 1
                    else:
                        tmplist = [nums[i],nums[j],nums[tmpi],nums[tmpj]]   
                        resultlist.append(tmplist)
                        tmpi += 1
                        tmpj -= 1
        func = lambda x,y:x if y in x else x + [y]
        return reduce(func,[[],]+resultlist)

2. Better solution for “N-2”Sum Problem. ref link

class Solution(object):
    def fourSum(self, nums, target):
        nums.sort()
        results = []
        self.findNsum(nums, target, 4, [], results)
        return results

    def findNsum(self, nums, target, N, result, results):
        if len(nums) < N or N < 2: return

        # solve 2-sum
        if N == 2:
            l,r = 0,len(nums)-1
            while l < r:
                if nums[l] + nums[r] == target:
                    results.append(result + [nums[l], nums[r]])
                    l += 1
                    r -= 1
                    while l < r and nums[l] == nums[l - 1]:
                     l += 1
                    while r > l and nums[r] == nums[r + 1]:
                        r -= 1
                elif nums[l] + nums[r] < target:
                    l += 1
                else:
                    r -= 1
        else:
            for i in range(0, len(nums)-N+1):   # careful about range
                if target < nums[i]*N or target > nums[-1]*N:  # take advantages of sorted list
                    break
                if i == 0 or i > 0 and nums[i-1] != nums[i]:  # recursively reduce N
                    self.findNsum(nums[i+1:], target-nums[i], N-1, result+[nums[i]], results)
        return

Here are some ways to remove duplicates in List:

1. Check every item to be appended into the list:

mylist = [1,2,3,4,5]
newitem = 3
if newitem not in mylist:
    mylist.append(newitem)

2. Use Set

mylist = [1,2,3,4,5]
mylist= list(set(mylist))

Note that if the list item is editable, which means it is not int, string, tuple or something others, a type error may occur:

mylist = [[1,2,3],[2,3,4],[4,5,6]]
newitem = [3,4,5]
mylist = list(set(mylist))

TypeError: unhashable type: ‘list’

3. Use function: “reduce” ref link

In [5]: ids = [1,4,3,3,4,2,3,4,5,6,1]
In [6]: func = lambda x,y:x if y in x else x + [y]
In [7]: reduce(func, [[], ] + ids)
 Out[7]: [1, 4, 3, 2, 5, 6]

Here, lambda x,y:x if y in x else x + [y] means lambda x,y: y in x and x or x+[y] .

4. A specific method in this Problem
As we use the sorted list in this problem, during constructing the result list, we can skip same numbers in the neighbor.

if nums[l] + nums[r] == target:
    results.append(result + [nums[l], nums[r]])
    l += 1
    r -= 1 
    #skip same numbers after appending
    while l < r and nums[l] == nums[l - 1]: 
        l += 1
    while r > l and nums[r] == nums[r + 1]:
        r -= 1
elif nums[l] + nums[r] < target:
    l += 1
else:
    r -= 1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值