DeepSeek LeetCode 1755 最接近目标值的子序列和 public int minAbsDifference(int[] nums, int goal)
这个问题可以通过将数组分成两半并枚举所有子序列和然后排序和二分查找来高效解决时间复杂度为 O(2^{n/2} \cdot n)。算法思路1. 将数组 nums 分成两部分 left 和 right长度分别为 n/2 和 n - n/2。2. 分别枚举两部分的所有子序列包括空序列得到两个和列表 sumsL 和 sumsR。3. 对 sumsR 排序。4. 遍历 sumsL 中的每个和 sumL在 sumsR 中二分查找最接近 goal - sumL 的值更新最小绝对差。5. 返回最小绝对差。代码实现javaimport java.util.ArrayList;import java.util.Collections;import java.util.List;public class Solution {public int minAbsDifference(int[] nums, int goal) {int n nums.length;// 分成两半int[] left new int[n / 2];int[] right new int[n - n / 2];System.arraycopy(nums, 0, left, 0, left.length);System.arraycopy(nums, n / 2, right, 0, right.length);// 生成所有子序列和ListInteger sumsL generateSubsetSums(left);ListInteger sumsR generateSubsetSums(right);// 排序右半部分Collections.sort(sumsR);int ans Integer.MAX_VALUE;for (int sumL : sumsL) {int target goal - sumL;// 二分查找最接近 target 的值int idx Collections.binarySearch(sumsR, target);if (idx 0) {// 精确匹配绝对差为 0return 0;}// 插入点-idx-1int insertPos -idx - 1;// 检查插入点左边的元素if (insertPos 0) {int sumR sumsR.get(insertPos - 1);ans Math.min(ans, Math.abs(sumL sumR - goal));}// 检查插入点右边的元素if (insertPos sumsR.size()) {int sumR sumsR.get(insertPos);ans Math.min(ans, Math.abs(sumL sumR - goal));}}return ans;}// 枚举数组所有子序列的和包括空序列private ListInteger generateSubsetSums(int[] arr) {ListInteger sums new ArrayList();int m arr.length;// 使用位掩码枚举所有子集for (int mask 0; mask (1 m); mask) {int sum 0;for (int i 0; i m; i) {if ((mask (1 i)) ! 0) {sum arr[i];}}sums.add(sum);}return sums;}}复杂度分析· 时间复杂度生成子集和需要 O(2^{n/2})排序右半部分 O(2^{n/2} \log(2^{n/2}))遍历左半部分时每次二分查找 O(\log(2^{n/2}))总体为 O(2^{n/2} \cdot n)。· 空间复杂度存储两个子集和列表O(2^{n/2})。优化建议· 若数组长度较小如 ≤ 20可直接枚举所有子序列无需分半。· 生成子集和时可用递归或迭代优化常数但位掩码法已足够清晰。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2552080.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!