• 2035. 将数组分成两个数组并最小化数组和的差 折半搜索


    2035. 将数组分成两个数组并最小化数组和的差

    给你一个长度为 2 * n 的整数数组。你需要将 nums 分成 两个 长度为 n 的数组,分别求出两个数组的和,并 最小化 两个数组和之 差的绝对值 。nums 中每个元素都需要放入两个数组之一。

    请你返回 最小 的数组和之差。

    示例 1:

    输入:nums = [3,9,7,3]
    输出:2
    解释:最优分组方案是分成 [3,9] 和 [7,3] 。
    数组和之差的绝对值为 abs((3 + 9) - (7 + 3)) = 2 。
    

    示例 2:

    输入:nums = [-36,36]
    输出:72
    解释:最优分组方案是分成 [-36] 和 [36] 。
    数组和之差的绝对值为 abs((-36) - (36)) = 72 。
    

    示例 3:

    输入:nums = [2,-1,0,4,-2,-9]
    输出:0
    解释:最优分组方案是分成 [2,4,-9] 和 [-1,0,-2] 。
    数组和之差的绝对值为 abs((2 + 4 + -9) - (-1 + 0 + -2)) = 0 。
    

    提示:

    • 1 <= n <= 15
    • nums.length == 2 * n
    • -10^7 <= nums[i] <= 10^7

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

    做题结果

    失败。这类折半搜索写的少,思路上模糊的有一点:减掉平均数,正负号之类的概念,还是看了一下其他题解(折半的主要方向,打正负号的概念),才有了思路

    方法:折半搜索

    1. 一个数组切成左右两部分。长度30不能枚举,但是15是可以枚举的。枚举所有一半元素放入两个集合的情况,放入集合A的记为正数,放入集合B的写为负数,分别用二进制的1和0标识。我们的目标,是让两个数组的差值,尽可能地接近于0.

    2. 怎么求 dp子集和。首先全0的情况,就是求和取相反数。然后每多一个取正的数,把最后这个加入的数加两次。为什么加两次呢?比如 [3],开始取负号是-3,如果把它改成取正号,需要变成3,3-(-3)=6,所以要加两次。

    3. 取完之后,就变成两个 dp ,暂时叫做 A 和 B。我们把 B 按照正号的数目分类,然后放入TreeSet中(这一步因为是连续的,外层也可用长度n+1的数组代替,TreeSet也可后续用二分代替)

    4. 我们一共要取 n 个数。已知前半取了 x 个,后半就取 n-x个。前半取到数值是 A[X],我们希望后半取到的长度为 n-x 的数中,尽量取尽可能接近 -A[X] 的值,可以使用有序集合的性质,floor,ceiling上下找一下,得到两个值,求和尽可能地小,比较更小的值,放入答案。

    1. class Solution {
    2. public int minimumDifference(int[] nums) {
    3. int n = nums.length/2;
    4. int[] sums1 = getSum(nums,0);
    5. int[] sums2 = getSum(nums,n);
    6. //按长度分类。。。
    7. Map> map = new HashMap<>();
    8. for(int i = 0; i < 1<
    9. int cnt = Integer.bitCount(i);
    10. map.putIfAbsent(cnt,new TreeSet<>());
    11. map.get(cnt).add(-sums2[i]);
    12. }
    13. int ans = Integer.MAX_VALUE;
    14. for(int i = 0; i < 1<
    15. int cnt = Integer.bitCount(i);
    16. int v = sums1[i];
    17. TreeSet set = map.get(n-cnt);
    18. Integer a = set.floor(v);
    19. if(a!=null)ans = Math.min(ans,Math.abs(v-a));
    20. Integer b = set.ceiling(v);
    21. if(b!=null) ans = Math.min(ans,Math.abs(v-b));
    22. }
    23. return ans;
    24. }
    25. private int[] getSum(int[] nums, int move){
    26. int n = nums.length/2;
    27. int[] sums1 = new int[1<
    28. int total = 0;
    29. for(int i = move; i < n+move; i++){
    30. total+=nums[i];
    31. }
    32. sums1[0] = -total;
    33. for(int i = 1; i < 1<
    34. int lastIndex = Integer.bitCount((i&(-i))-1);
    35. sums1[i] = sums1[i&(i-1)]+nums[lastIndex+move]*2;
    36. }
    37. return sums1;
    38. }
    39. }

  • 相关阅读:
    【强化学习论文合集】IJCAI-2021 强化学习论文
    人工智能常用资料及网址
    (三)JPA - EntityManager的使用
    MySQL 查询优化思路
    【C++】setjmp,longjmp的详细使用说明
    为什么要选快鲸智慧社区系统?四大突出优势值得信赖
    pcl--第十一节 点云外接立方体和点云模板匹配
    【无标题】
    推荐一款企业管理专用低代码工具,实现开发系统自由!
    基于Java jsp+mysql+Spring的汽车出租平台租赁网站平台设计和实现
  • 原文地址:https://blog.csdn.net/yu_duan_hun/article/details/125899854