将数组分成两个数组并最小化数组和的差(折半搜索+二分)

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了将数组分成两个数组并最小化数组和的差(折半搜索+二分)相关的知识,希望对你有一定的参考价值。

将数组分成两个数组并最小化数组和的差(折半搜索+二分)

2 n ≤ 30 2n\\le 30 2n30,显然是折半搜索。

预处理前一半和后一半的选正的差值。

然后排序去重。

最后扫一遍,枚举正号的个数: i ∈ [ 0 , n ] i\\in[0,n] i[0,n]

前一半正号选了个 i i i个,那么后一半正号也要选 i i i个,这里两者个数才会相等。

然后二分找到最近的两个数。

class Solution {
    vector<int> s[16],t[16];
    int o[32768];
public:
    int minimumDifference(vector<int>& nums) {
        int n=nums.size()>>1,i,j,k,ans=1000000000;
        for(i=0;i<=n;i++)
        {
            s[i].clear();
            t[i].clear();
        }
        int st=1<<n;
        for(i=0;i<st;i++)
        {
            if(i)o[i]=o[i>>1]+(i&1); //二进制1的个数.
            else o[i]=0;
            for(j=k=0;j<n;j++)if(i>>j&1)k+=nums[j];
            else k-=nums[j];
            s[o[i]].push_back(k);
            for(j=k=0;j<n;j++)if(i>>j&1)k+=nums[j+n];
            else k-=nums[j+n];
            t[o[i]].push_back(k);
        }
        for(i=0;i<=n;i++)
        {
            sort(t[i].begin(),t[i].end());
            t[i].erase(unique(t[i].begin(),t[i].end()),t[i].end());//去重
        }
        for(i=0;i<=n;i++)for(auto &c:s[i])
        {
            auto it=lower_bound(t[i].begin(),t[i].end(),c);
            if(it!=t[i].end())ans=min(ans,*it-c);
            if(it!=t[i].begin())
            {
                it--;
                ans=min(ans,c-*it);
            }
        }
        return ans;
    }
};

以上是关于将数组分成两个数组并最小化数组和的差(折半搜索+二分)的主要内容,如果未能解决你的问题,请参考以下文章

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

2022-01-18:将数组分成两个数组并最小化数组和的差。 给你一个长度为 2 * n 的整数数组。你需要将 nums 分成 两个 长度为 n 的数组,分别求出两个数组的和,并 最小化 两个数组和之

数组:正整数数组分成2组使其和的差的绝对值最小

二分数组差值最大

[2017浙工大之江学院决赛 E] qwb和李主席(折半枚举,二分)

整数数组和的分治算法