将数组分成两个数组并最小化数组和的差(折半搜索+二分)
Posted Harris-H
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了将数组分成两个数组并最小化数组和的差(折半搜索+二分)相关的知识,希望对你有一定的参考价值。
将数组分成两个数组并最小化数组和的差(折半搜索+二分)
2 n ≤ 30 2n\\le 30 2n≤30,显然是折半搜索。
预处理前一半和后一半的选正的差值。
然后排序去重。
最后扫一遍,枚举正号的个数: 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 的数组,分别求出两个数组的和,并 最小化 两个数组和之