leetcode 3sum closest && 4sum

3sum closest

https://leetcode.com/problems/3sum-closest/
这题与3sum类似,维护i, j, k, 然后算mindiff就行.这里需要注意的是,是否需要去重复,题目说了只有一个solution,所以不用去重复。

my code:

class Solution(object):


    def threeSumClosest(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        if len(nums) < 3:
            return -1

        nums.sort()
        mindif = 100000
        res_sum = -1
        for i in xrange(len(nums) - 2):
            j = i + 1
            k = len(nums) - 1
            while j < k:
                mysum = nums[i] + nums[j] + nums[k]
                if mysum == target:
                    return mysum
                elif mysum < target:
                    if target - mysum < mindif:
                        mindif = target - mysum
                        res_sum = mysum
                    j += 1
                else:
                    if mysum - target < mindif:
                        mindif = mysum - target
                        res_sum = mysum
                    k -= 1
        return res_sum

4sum

https://leetcode.com/problems/4sum/

http://www.cnblogs.com/zuoyuan/p/3699384.html有思路

其实这里总结一下就是找出所有可能的两两和,存入hash表。然后这个hash表的key就变成了2sum的问题。找target - key 是否在hash中就行。

这里就不能用i,j,k 那种方法了,否则复杂度就是三次方了。所以这里其实应该用hash的办法。找出所有可能的两两和,存入hash表,然后再找到四元组里所有可能的最小值和第二小值,然后再利用差到hash表里面寻找对应的第三小值,和最大值。

class Solution(object):
    def fourSum(self, num, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[List[int]]
        """
        numLen, res, dict = len(num), set(), {}
        if numLen < 4: return []
        num.sort()
        for p in range(numLen - 1):
            for q in range(p+1, numLen): #枚举两两的值
                if num[p]+num[q] not in dict:
                    dict[num[p]+num[q]] = [(p,q)]
                else:
                    dict[num[p]+num[q]].append((p,q))
        for i in range(numLen-1):
            for j in range(i+1, numLen):#这里就是枚举两两的值
                T = target-num[i]-num[j]
                if T in dict:
                    for k in dict[T]:
                        if k[0] > j: res.add((num[i],num[j],num[k[0]],num[k[1]]))#这里只要T对应的两个值中的第一个值的index比j大就行。
        return [list(i) for i in res]

自己做题的时候还用了个笨办法,算出两两和的hash之后,计算所有两两和与target的差,然后看差是否依然在这个hash里面。其实最后算出来有很多重复的index。当然最后也还是可以利用set或者dict,通过leetcode测试

class Solution(object):
    def fourSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[List[int]]
        """

        if len(nums) <4:
            return []

        sumdict = {}
        for i in xrange(len(nums)):
            for j in xrange(i + 1, len(nums)):
                mysum = nums[i] + nums[j]
                if mysum not in sumdict:
                    sumdict[mysum] = [(i,j)]
                else:
                    sumdict[mysum].append((i,j))
        res = {}
        for k,v in sumdict.items():

            if target - k in sumdict:
                ind_list = sumdict[target - k]

                for x in ind_list:
                    for y in v:
                        res_ind_list = list(x) + list(y)

                        if len(set(res_ind_list)) == len(res_ind_list):
                            res_value = [ nums[ind] for ind in res_ind_list]
                            res_value.sort()
                            print res_value
                            if tuple(res_value) not in res:
                                res[tuple(res_value)] = 1


        return res.keys()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值