# 2035. Partition Array Into Two Arrays to Minimize Sum Difference
###### tags: `Leetcode` `Hard` `Backtracking` `Bit Manipulation`
## 思路
发现n=15说明可能只能采用指数级别的暴力搜索
但是由于array的size可以到30说明我们不能对整个array暴力搜索
因此我们想办法把array平均分成两部分
前一部分取```i```个值 和为```x``` 那么后一部分我们就取```n-i```个值 和越接近```sum/2-x```越好
于是我们想到我们可以先对后半部分进行预处理 算出取```[0:n]```个值所有得到的结果
接着可以对前半部分用backtracking找出所有可能的值 然后binary search在后半部分找出最接近的
## Code
```java=
class Solution {
public int minimumDifference(int[] nums) {
int sum = 0;
for(int num:nums) sum += num;
int n = nums.length/2;
List<List<Integer>> secondHalf = new ArrayList<>();
for(int i=0; i<=n; i++) secondHalf.add(new ArrayList<>());
secondHalf.get(0).add(0);
for(int i=n; i<2*n; i++){
for(int j=n; j>=1; j--){
// the new element in secondHalf.get(j)==all the old element in secondHalf.get(j-1)+nums[i]
if(j==1){
secondHalf.get(j).add(nums[i]);
}
else if(secondHalf.get(j-1).size()==0) continue;
else{
for(int num:secondHalf.get(j-1)) secondHalf.get(j).add(num+nums[i]);
}
}
}
for(int i=0; i<n; i++){
Collections.sort(secondHalf.get(i));
}
int minDiff = Integer.MAX_VALUE;
//backtracking to take i elements from the first half and calculate its sum x
//binary search in the secondHalf.get(n-i) to find the sum closest to totalsum/2-x
List<List<Integer>> firstHalf = new ArrayList<>();
for(int i=0; i<=n; i++) firstHalf.add(new ArrayList<>());
for(int i=0; i<(1<<n); i++){
getSum(firstHalf, nums, i);
}
for(int i=0; i<=n; i++){
for(int j=0; j<firstHalf.get(i).size(); j++){
int firstSum = firstHalf.get(i).get(j);
int secondSum = binarySearch(sum/2-firstSum, secondHalf.get(n-i));
minDiff = Math.min(minDiff, Math.abs(2*(firstSum+secondSum)-sum));
}
}
return minDiff;
}
private int binarySearch(int target, List<Integer> nums){
int start = 1, end = nums.size();
while(start<end){
int mid = start+(end-start)/2;
if(nums.get(mid)<target){
start = mid+1;
}
else end = mid;
}
if(start!=nums.size() && Math.abs(nums.get(start)-target)<Math.abs(nums.get(start-1)-target)) return nums.get(start);
else return nums.get(start-1);
}
private void getSum(List<List<Integer>> firstHalf, int[] nums, int state){
int res = 0;
int n = nums.length/2;
int cnt = 0;
for(int i=0; i<n; i++){
if(((state>>i)&1)==1){
cnt++;
res += nums[i];
}
}
firstHalf.get(cnt).add(res);
}
}
```