leetcode 第888题和第16题

leetcode 第888题:公平的糖果交换

爱丽丝和鲍勃有不同大小的糖果棒:A[i] 是爱丽丝拥有的第 i 根糖果棒的大小,B[j] 是鲍勃拥有的第 j 根糖果棒的大小。因为他们是朋友,所以他们想交换一根糖果棒,这样交换后,他们都有相同的糖果总量。(一个人拥有的糖果总量是他们拥有的糖果棒大小的总和。)返回一个整数数组 ans,其中 ans[0] 是爱丽丝必须交换的糖果棒的大小,ans[1] 是 Bob 必须交换的糖果棒的大小。如果有多个答案,你可以返回其中任何一个。保证答案存在。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/fair-candy-swap

本题是一道简单题,输入是2个整数数组,我们需要从2个数组中分别取一个数出来进行交换,完成交换后2个数组的和相等。本题显然可以使用暴力法来解答。我们可以先计算出2个数组和的差,然后遍历第一个数组,对遍历到的每一个元素我们都可以计算出需要从第二个数组中交换的那个数,这样我们只需要判断需要交换的数是否在第二个数组中存在就可以了。

暴力解法

#Input: A = [1, 1], B = [2, 2]
#Output: [1, 2]
class Solution(object):
    def fairCandySwap(self, A, B):
        """
        :type A: List[int]
        :type B: List[int]
        :rtype: List[int]
        """
        diff = sum(A) - sum(B)
        for i in range(len(A)):
            target = (2*A[i] - diff)
            if target % 2 == 0:
                target /= 2
                if target in B:
                    return [A[i], target]
        

但其实我们还可以有更高明的解法。我们可以使用先排序再使用双指针的解法来降低算法的复杂度。先对2个数组进行排序,然后使用双指针寻找需要的2个数。

先排序,再双指针

class Solution(object):
    def fairCandySwap(self, A, B):
        """
        :type A: List[int]
        :type B: List[int]
        :rtype: List[int]
        """
        A, B = sorted(A), sorted(B)
        diff = sum(A) - sum(B)
        i, j = 0, 0
        while(i<len(A) and j<len(B)):
            if 2*(A[i]-B[j]) < diff:
                i += 1
            elif 2*(A[i]-B[j]) > diff:
                j += 1
            else:
                res = [A[i], B[j]]
                break
        return res

面对数组问题,我们经常会使用的一个策略就是排序,排完序之后可以使用数组有序的这一先验知识避免不必要的遍历。例如 leetcode 第16题就是这样的一个例子。

leetcode 第16题

给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/3sum-closest

我们需要从一个整数数组中找到3个数使它们的和最接近一个目标值。如果使用暴力法进行遍历,那么就是三层循环,会使算法具有较高的时间复杂度。因此我们可以先将数组排序,然后写一层外循环,这样内部的2层循环我们可以借助数组有序这样一个先验知识简化成一层循环,这一层循环可以使用双指针构建滑动窗口来实现。

先排序,再双指针

#Input:nums = [-1,2,1,-4], target = 1
#Output: 2 (-1 + 2 + 1 = 2)
def threeNumSum(n, arr, target):
    arr = sorted(arr)
    numSum = arr[0] + arr[1] + arr[2]
    for i in range(n-2):
        l, r = i + 1, n - 1
        while l < r:
            tmp = arr[i] + arr[l] + arr[r]
            if abs(tmp-target) < abs(numSum-target):
                numSum = tmp
            if tmp > target:
                r -= 1
            elif tmp < target:
                l += 1
            else:
                return target
    return numSum
           
if __name__ == '__main__':
    n = 4
    arr = [-1, 2, 1, -4]
    target = 1
    num_sum = threeNumSum(n, arr, target)
    print(num_sum)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值