# 2163. Minimum Difference in Sums After Removal of Elements
###### tags: `Leetcode` `Hard` `Dynamic Programming` `Greedy` `Three Pass`
Link: https://leetcode.com/problems/minimum-difference-in-sums-after-removal-of-elements/description/
## 思路
因为删除```n```个元素之后,剩余的```2n```个元素会自然地分成前后两个部分,所以我们很自然地会考察这两个部分的分界点在哪里。假设分界点在位置```k```,那么sum_first怎么选?自然就是```nums[0:k]```里面和最小的```n```个元素;sum_second怎么选?自然就是```nums[k+1:n-1]```里面和最大的```n```个元素。
于是问题转化为,如何高效地在前```k```个元素里找和最小的```n```个元素?显然我们就找最小的```n```个元素即可。从做往右遍历的时候,用一个优先队列始终保存```n```个最小的元素,就可以得到```k```左边最小(包含```k```)的```n```个元素的和,记做```left[k]```。同理我们可以用NlogN的时候,从右往左遍历,得到```rightMax[k]```,表示```k```右边最大(不包含```k```)的```n```个元素的和。
本题的答案就是找一个全局最小的```left[k]-right[k]```
## Code
```java=
class Solution {
public long minimumDifference(int[] nums) {
int n = nums.length;
long[] left = new long[n];
long[] right = new long[n];
long sum = 0;
Queue<Integer> pq = new PriorityQueue(Collections.reverseOrder());
for(int i=0; i<n; i++){
int num = nums[i];
pq.add(num);
sum += num;
if(pq.size()>n/3){
sum -= pq.poll();
}
left[i] = sum;
}
sum = 0;
pq = new PriorityQueue<>();
for(int i=n-1; i>=0; i--){
right[i] = sum;
int num = nums[i];
pq.add(num);
sum += num;
if(pq.size()>n/3){
sum -= pq.poll();
}
}
long ans = (long)Double.MAX_VALUE;
for(int i=n/3-1; i<2*(n/3); i++){
if(ans>left[i]-right[i]) ans = left[i]-right[i];
}
return ans;
}
}
```