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)