《剑指offer》52、两数之和/三数之和

offer52的题目要求是:输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。

两数之和

当然,即便输入的不是一个递增排序的数组,我们也可以sort一下变成一个完成排序的数组。数组的递增性给我们带来了许多便利,比如我们可以用双指针从头和结尾开始遍历:

# offer52-solution
class Solution:
    def FindNumbersWithSum(self, array, tsum):
        if not array:
            return []
        head = 0
        tail = len(array)-1
        a = b = tsum
        while (head != tail):
            if array[head]+array[tail] < tsum:
                head = head + 1
            elif array[head]+array[tail] > tsum:
                tail = tail - 1
            else:
                if array[head]*array[tail] <= a*b:
                    a,b = array[head],array[tail]
                head = head + 1
        if a*b == tsum*tsum:
            return []
        return [a,b]

三数之和

尽管不是offer52的要求,我们来简单讨论一下三数之和。要求和上述一样:输入一个递增排序的数组,判断数组中是否存在三个数之和为0,若是,输出该三个数。为了简单起见,即便存在多组解,我们只输出一组即可。

其实原题目给出的数组并不是递增的,但是反正我们sort一下夜不费事——排序是为了让元素之间呈现出某种规律,使得后续的处理会简单很多,这就是所谓的没有规律就要创造规律了。题目的要求是三个数之和为0,这样可以方便我们使用正数+负数的技巧。代码我自己没有写,参考:
LintCode三数之和系列问题

# offer52*-solution
# the sum of three nums
class Solution:
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        nums.sort()
        count = len(nums)
        collect = []
        for i in range(count):
            left = i+1
            right = count-1
            #避免重复找同一个数据
            if i >0 and nums[i] == nums[i-1]:
                left +=1
                continue
            #数据按小到大排列,每次选取nums[i],在其后寻找符合a + b + c = 0的两个数据
            while left < right:
                sum = nums[i] + nums[left] + nums[right]
                if sum == 0:
                    col = [nums[i],nums[left],nums[right]]
                    collect.append(col)
                    left+=1
                    right-=1
                    #循环中nums[i]已确定,当再确定1个数时,另一个数也确定,左右端任一端出现重复均可跳过
                    while nums[left] == nums[left-1] and left < right:
                        left+=1
                    while nums[right] == nums[right+1] and left < right:
                        right-=1
                if sum<0:
                    left+=1
                elif sum > 0:
                    right-=1
        return collect          
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值