1. 程式人生 > 其它 >LeetCode 1755. 最接近目標值的子序列和(狀態列舉 + 雙指標)

LeetCode 1755. 最接近目標值的子序列和(狀態列舉 + 雙指標)

技術標籤: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} 2401012,肯定超時
  • 分治列舉,取出一半來列舉 2 20 ≈ 1 0 6 2^{20} \approx 10^6 220106,然後對兩半邊的狀態排序,雙指標求解
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阿明),一起加油、一起學習進步!
Michael阿明