LeetCode 1755. 最接近目標值的子序列和(狀態列舉 + 雙指標)
阿新 • • 發佈:2021-02-10
技術標籤:LeetCode
文章目錄
1. 題目
給你一個整數陣列 nums 和一個目標值 goal 。
你需要從 nums 中選出一個子序列,使子序列元素總和最接近 goal 。
也就是說,如果子序列元素和為 sum ,你需要 最小化絕對差 abs(sum - goal)
。
返回 abs(sum - goal)
可能的 最小值 。
注意,陣列的子序列是通過移除原始陣列中的某些元素(可能全部或無)而形成的陣列。
示例 1:
輸入:nums = [5,-7,3,5], goal = 6
輸出:0
解釋:選擇整個陣列作為選出的子序列,元素和為 6 。
子序列和與目標值相等,所以絕對差為 0 。
示例 2:
輸入:nums = [7,-9,15,-2], goal = -5
輸出:1
解釋:選出子序列 [7,-9,-2] ,元素和為 -4 。
絕對差為 abs(-4 - (-5)) = abs(1) = 1 ,是可能的最小值。
示例 3:
輸入:nums = [1,2,3], goal = -7
輸出:7
提示:
1 <= nums.length <= 40
-10^7 <= nums[i] <= 10^7
-10^9 <= goal <= 10^9
來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/closest-subsequence-sum
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。
2. 解題
- 直接列舉,時間複雜度 2 40 ≈ 1 0 12 2^{40} \approx 10^{12} 240≈1012,肯定超時
- 分治列舉,取出一半來列舉 2 20 ≈ 1 0 6 2^{20} \approx 10^6 220≈106,然後對兩半邊的狀態排序,雙指標求解
class Solution {
public:
int minAbsDifference(vector<int>& nums, int goal) {
int n = nums.size();
vector< int> arr1, arr2;
getsum(nums, 0, n/2, arr1);
getsum(nums, n/2, n, arr2);
int i = 0, j = arr2.size()-1, n1 = arr1.size();
int diff = INT_MAX, sum;
while(i < n1 && j >= 0)
{
sum = arr1[i] + arr2[j];
diff = min(diff, abs(sum-goal));
if(sum > goal)
j--;
else if(sum < goal)
i++;
else
break;
}
return diff;
}
void getsum(vector<int>& nums, int l, int r, vector<int>& arr)
{
int n = r-l;
arr.resize(1<<n);
for(int i = 0; i < (1<<n); i++)
{
for(int j = 0; j < n; j++)
{
if(i & (1 << j))
continue;// i 狀態 包含 j 數字
arr[i+(1<<j)] = arr[i] + nums[l+j];
}
}
sort(arr.begin(), arr.end());
}
};
1180 ms 29.2 MB C++
我的CSDN部落格地址 https://michael.blog.csdn.net/
長按或掃碼關注我的公眾號(Michael阿明),一起加油、一起學習進步!