Leetcode | 16. 3Sum Closest twoPoint方法拓展

Givenan array nums of n integers and an integer target, find three integers in nums such that the sum is closestto target. Return thesum of the three integers. You may assume that each input would have exactlyone solution.

Example:

Given array nums = [-1, 2, 1, -4], and target = 1.

 

The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).

这一题让你找到三个数,使得这三个数的和和target的差的绝对值最小

这一题可以转换为传统的twoPoint问题的解

这一题的子问题是,给定从小到大拍好序的数组,给定target和A和B,以及限定A和B在数组中的索引范围,使得abs(target– A – B)最小

假设数组为nums,A索引的取值范围为0 ~ IndexA,B的索引取值范围为IndexB ~ len(nums) - 1,

那么我们首先设定索引left和right,当nums[left] + nums[right] > target的时候,left++,当nums[left] + nums[right] < target的时候,right--,当nums[left] + nums[right] == target说明这个时候已经找到了绝对值差最小的组合,直接返回组合就好了,

这就是经典的twoPoint方法,

然后我们再来证明这个方法的正确性

假设存在NeedLeft和NeedRight,使得abs(nums[NeedLeft] + nums[NeedRight] – target)最小,那么我们在使用twoPoint方法的时候,必定有一个瞬间,left == NeedLeft,right != NeedRight,或者是left != NeedLeft,right == NeedRight,

可以证明,前一种情况其值绝对是nums[left] + nums[right] > target,这个时候right会不断减,直到left == NeedLeft,right== NeedRight,

对于后一种情况,同理,nums[left] + nums[right] < target绝对成立,这个时候left会不断的加,直到left == NeedLeft,right== NeedRight,

也就是说,NeedLeft和NeedRight这个最优的组合方案一定可以找到

然后回到这一题,它让你找三个数,我们可以通过对第二个数的位置进行分类,在第二个数的位置的左边和右边范围找A和B,使得abs(nums[NeedLeft] + nums[NeedRight] –target2)最小,就能得到最终的结果,这里需要注意的是,target2 = target – B,

总共只需要两层循环就能解决问题

通过这一题还学会了python里面的sorted和sort的使用,sorted(nums,key,reverse);接受三个参数,第一个参数是输入数组,第二个参数是一个函数,可以使用类似lambdax:x[0]的lambda函数或者是直接输入函数,第三个参数是一个bool类型,表示结果是否翻转,还需要注意的是sorted不会改变输入的数组,但是会返回一个排好序的数组,而list.sort()会改变原数组,返回的是None,sort接受两个参数,分别是sorted的第二和第三个参数,这一点上和sorted是一样的

class Solution(object):
    def threeSumClosest(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        theLastSum = nums[0] + nums[1] + nums[2]
        theLastL = abs(target - theLastSum)
        length = len(nums)
        nums.sort()
        for i in range(1, length - 1):
            left = 0
            right = length - 1
            while True:
                theTmpTar = target - nums[i]
                sumTmp = nums[left] + nums[right]
                if sumTmp == theTmpTar: return sumTmp + nums[i]
                if abs(sumTmp - theTmpTar) < theLastL:
                    theLastL = abs(sumTmp - theTmpTar)
                    theLastSum = sumTmp + nums[i]
                if sumTmp < theTmpTar: left += 1
                else: right -= 1
                if right == i or left == i: break;
        return theLastSum

猜你喜欢

转载自blog.csdn.net/u012737193/article/details/80737157