leetcode 5897 Partition Array Into Two Arrays to Minimize Sum Difference

  • you are given an integer array nums of 2 * n integers. You need to partition nums into two arrays of length n to minimize the absolute difference of the sums of the arrays. To partition nums, put each element of nums into one of the two arrays.Return the minimum possible absolute difference.

在这里插入图片描述在这里插入图片描述

  • 引入概念:二分搜索,将搜索空间一分为二,可以显著降低复杂度
  • 将nums数组分成前半部分和后半部分,每一部分分别有n个元素.在每一部分中分别搜索可能的差值。
    • 使用列表对象数组left。left[i]记录在nums数组的前半部分取i个元素放入array1时(于是其余的n - i个元素放入array2),在前半部分的意义下array1和array2的差值。
    • 使用列表对象数组right,执行和列表对象数组left完全一致的操作;
  • 取i个元素可以使用二进制模拟的方式实现。
  • 合并:对于列表对象数组left的每一个i值,必须在right[n - i]中搜索结果。选取两者元素之和绝对值最小的元素即可。
    • 方式是排序+双指针法。

AC代码如下:

class Solution {
    public int minimumDifference(int[] nums) {
        //保存左侧,当arr1的长度为i时,arr1和arr2的可能的差值列表
        List<Integer>[] left = new List[nums.length/2 + 1];
        //保存右侧,当arr1的长度为i时,arr1和arr2的可能的差值列表
        List<Integer>[] right = new List[nums.length/2 + 1];
        for(int i = 0;i<left.length;i++) {
            left[i] = new ArrayList<>();
            right[i] = new ArrayList<>();
        }
        //枚举每一种可能的选择
        for(int i = 0;i<((1<<nums.length/2));i++)
        {
            int sum = 0;
            int sum_1 = 0;
            int cout = 0;  //选择中位于数组1的个数
            for(int j = 0;j<nums.length / 2;j++)
            {
                if(((i >> j) & 1 )== 1)  //表明被选择到第一个数组中了
                {
                    cout+=1;
                    sum_1+=nums[j + nums.length/2];
                    sum += nums[j];
                }
                else
                {
                    sum_1-=nums[j+nums.length/2];
                    sum -= nums[j];
                }
            }
            left[cout].add(sum);
            right[cout].add(sum_1);
        }
        //所有差值已经计算完毕
        int ans = Integer.MAX_VALUE;
        for(int i = 0;i<nums.length / 2;i++)
        {
            left[i].sort(new Comparator<Integer>() {
                @Override
                public int compare(Integer o1, Integer o2) {
                    return Integer.compare(o1,o2);
                }
            });
            right[nums.length/2 - i].sort(new Comparator<Integer>() {
                @Override
                public int compare(Integer o1, Integer o2) {
                    return Integer.compare(o1,o2);
                }
            });
            int j = 0;
            int k  = right[nums.length / 2 - i].size() - 1;
            while(k>=0 && j<left[i].size())
            {
                ans = Math.min(ans,Math.abs(left[i].get(j) + right[nums.length/2 - i].get(k)));
                if(ans == 0)
                    return ans;
                if(left[i].get(j) + right[nums.length/2 - i].get(k) > 0)
                    k--;
                else j++;
            }
        }
        return ans;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值