最接近目标值的子序列和

简介: 最接近目标值的子序列和

最接近目标值的子序列和

给你一个整数数组 nums 和一个目标值 goal 。

你需要从 nums 中选出一个子序列,使子序列元素总和最接近 goal 。也就是说,如果子序列元素和为 sum ,你需要 最小化绝对差 abs(sum - goal) 。

返回 abs(sum - goal) 可能的 最小值 。

注意,数组的子序列是通过移除原始数组中的某些元素(可能全部或无)而形成的数组。

**提示:
1 <= nums.length <= 40
-107 <= nums[i] <= 107
-10^9^ <= goal <= 10^9^**

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/closest-subsequence-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

一、解题思路

看题目数据范围,goal在[-10^9^,10^9^]如果背包搞二维表超时了背包动态规划不能用但是数组个数少,用分治
image.png
左部分,右部分每个数要跟不要全部展开,2^20^,百万级别
image.png
最接近目标的
有可能是只用左侧的这20个数搞出来的
也有可能是只用右侧的这20个数搞出来的
或者左侧给我一个累加和我看看右侧选哪个累加和加完之后离它最近。
你把左侧搞出来了,最多100万个累加和右侧最多搞定了100万个的累加和
左侧的所有累加和你都去找右侧哪个跟它加完之后最接近
这个过程不就是相当于100万乘以log100万这样一个复杂度吗?因为你把所有的累加和和加到有序表里去了

二、代码

    public static int[] l = new int[1 << 20];
    public static int[] r = new int[1 << 20];

    public static int minAbsDifference(int[] nums, int goal) {
        if (nums == null || nums.length == 0) {
            return goal;
        }
        int le = process(nums, 0, nums.length >> 1, 0, 0, l);
        int re = process(nums, nums.length >> 1, nums.length, 0, 0, r);
        Arrays.sort(l, 0, le);
        Arrays.sort(r, 0, re--);
        int ans = Math.abs(goal);
        for (int i = 0; i < le; i++) {
            int rest = goal - l[i];
            while (re > 0 && Math.abs(rest - r[re - 1]) <= Math.abs(rest - r[re])) {
                re--;
            }
            ans = Math.min(ans, Math.abs(rest - r[re]));
        }
        return ans;
    }

    public static int process(int[] nums, int index, int end, int sum, int fill, int[] arr) {
        if (index == end) {
            arr[fill++] = sum;
        } else {
            fill = process(nums, index + 1, end, sum, fill, arr);
            fill = process(nums, index + 1, end, sum + nums[index], fill, arr);
        }
        return fill;
    }

总结

在做题的时候,我们需要分析题目的数据量,根据数据量来猜解法
例如这一题中,我们可以使用分治的思想

相关文章
|
1月前
|
算法 C++
【动态规划】【子序列除重】【C++算法】1987不同的好子序列数目
【动态规划】【子序列除重】【C++算法】1987不同的好子序列数目
|
1月前
|
算法
|
1月前
|
算法 测试技术 C#
【折半处理 二分查找】1755. 最接近目标值的子序列和
【折半处理 二分查找】1755. 最接近目标值的子序列和
【折半处理 二分查找】1755. 最接近目标值的子序列和
|
1月前
|
机器学习/深度学习 算法 测试技术
【线段树】【区间更新】2916. 子数组不同元素数目的平方和 II
【线段树】【区间更新】2916. 子数组不同元素数目的平方和 II
【线段树】【区间更新】2916. 子数组不同元素数目的平方和 II
|
1月前
|
C++
数的三次方根(二分查找的应用)
数的三次方根(二分查找的应用)
|
1月前
|
算法 测试技术 C#
二分查找|前缀和|滑动窗口|2302:统计得分小于 K 的子数组数目
二分查找|前缀和|滑动窗口|2302:统计得分小于 K 的子数组数目
|
1月前
|
算法
回溯-求出数组的所有子序列【学习算法】
回溯-求出数组的所有子序列【学习算法】
34 0
|
1月前
|
算法 程序员
【算法训练-动态规划 二】【线性DP问题】连续子数组的最大和、乘积最大子数组、最长递增子序列
【算法训练-动态规划 二】【线性DP问题】连续子数组的最大和、乘积最大子数组、最长递增子序列
70 0
|
1月前
|
存储 算法 程序员
【算法训练-数组 一】【数组子集】:最长无重复子数组
【算法训练-数组 一】【数组子集】:最长无重复子数组
29 0
|
6月前
|
算法 测试技术 C#
C++ 算法:区间和的个数
C++ 算法:区间和的个数