Trace
最接近目标值的子序列和
传送门:https://leetcode-cn.com/problems/closest-subsequence-sum/
Problem
给你一个整数数组 nums
和一个目标值 goal
。
你需要从 nums
中选出一个子序列,使子序列元素总和最接近 goal
。也就是说,如果子序列元素和为 sum
,你需要 最小化绝对差 abs(sum - goal)
。
返回 abs(sum - goal)
可能的 最小值 。
注意,数组的子序列是通过移除原始数组中的某些元素(可能全部或无)而形成的数组。
示例 1:
1 | 输入:nums = [5,-7,3,5], goal = 6 |
示例 2:
1 | 输入:nums = [7,-9,15,-2], goal = -5 |
示例 3:
1 | 输入:nums = [1,2,3], goal = -7 |
提示:
1 | 1 <= nums.length <= 40 |
思路
枚举子集的基础题目:https://leetcode-cn.com/problems/subsets/
两种求所有子集的方法:
- $dfs$
- 位运算
枚举所有子集的时间复杂度为$2^n$,$n=40$,加上每次需要求和运算,时间复杂度太高。
一个技巧:将$n=40$的数组拆成两部分,每部分元素个数为20,枚举每一部分所有子集的时间复杂度为$2^{20}\approx10^6$,接着枚举每一部分所有子集的和,记为$sum1$,$sum2$,时间复杂度$O((n/2)*2^{n/2})$,大概在$10^7$左右。
原数组的子序列和,必然为下列三者之一:
$sum1$中某个元素
$sum2$中某个元素
- $sum1$中某个元素与$sum2$中某个元素之和
前两种情况直接遍历就可以得到,第三种情况为给定两个有序数组,分别从两个数组中各取出一个数字,使他们的和最接近$goal$,相关题目:https://leetcode-cn.com/problems/two-sum-ii-input-array-is-sorted/。
考虑双指针,将$i$指向$sum1$中第一个元素,将$j$指向$sum2$中最后一个元素,每次计算$sum1[i]$与$sum2[j]$的和$s$。
如果$s<goal$,则对于当前的$i$,剩余所有的$j$都不用考虑了(和只可能更小),于是将$i$右移一个位置;
如果$s>=goal$,则对于当前的$j$,剩余所有的$i$都不需要考虑了(和只可能更大),于是将$j$左移一个位置。
这部分排序时间复杂度为$O(2^{n/2}log{2^{n/2}})$,大概在$10^7$左右,双指针时间复杂度$O(2^{n/2})$。
程序
1 | class Solution { |