class Solution {
public:
int minimumDifference(vector<int>& nums) {
}
};
2035. 将数组分成两个数组并最小化数组和的差
给你一个长度为 2 * n
的整数数组。你需要将 nums
分成 两个 长度为 n
的数组,分别求出两个数组的和,并 最小化 两个数组和之 差的绝对值 。nums
中每个元素都需要放入两个数组之一。
请你返回 最小 的数组和之差。
示例 1:
输入:nums = [3,9,7,3] 输出:2 解释:最优分组方案是分成 [3,9] 和 [7,3] 。 数组和之差的绝对值为 abs((3 + 9) - (7 + 3)) = 2 。
示例 2:
输入:nums = [-36,36] 输出:72 解释:最优分组方案是分成 [-36] 和 [36] 。 数组和之差的绝对值为 abs((-36) - (36)) = 72 。
示例 3:
输入:nums = [2,-1,0,4,-2,-9] 输出:0 解释:最优分组方案是分成 [2,4,-9] 和 [-1,0,-2] 。 数组和之差的绝对值为 abs((2 + 4 + -9) - (-1 + 0 + -2)) = 0 。
提示:
1 <= n <= 15
nums.length == 2 * n
-107 <= nums[i] <= 107
原站题解
golang 解法, 执行用时: 624 ms, 内存消耗: 6.9 MB, 提交时间: 2023-08-16 17:31:43
func minimumDifference(nums []int) int { n := len(nums) / 2 a := nums[:n] res := make([][]int, n+1) for i := 0; i < 1<<n; i++ { sum, cnt := 0, 0 for j, v := range a { if i>>j&1 > 0 { // 1 视作取正 sum += v cnt++ } else { // 0 视作取负 sum -= v } } res[cnt] = append(res[cnt], sum) // 按照取正的个数将元素和分组 } for _, b := range res { sort.Ints(b) // 排序,方便下面二分 } ans := math.MaxInt64 a = nums[n:] for i := 0; i < 1<<n; i++ { sum, cnt := 0, 0 for j, v := range a { if i>>j&1 > 0 { sum += v cnt++ } else { sum -= v } } // 在对应的组里二分最近的数 b := res[cnt] j := sort.SearchInts(b, sum) if j < len(b) { ans = min(ans, b[j]-sum) } if j > 0 { ans = min(ans, sum-b[j-1]) } } return ans } func min(a, b int) int { if a > b { return b } return a }
python3 解法, 执行用时: 2380 ms, 内存消耗: 19 MB, 提交时间: 2023-08-16 17:30:03
''' 折半枚举+排序+二分 两个数组和之差可以视作从 nums 中选 n 个数取正号,其余 n 个数取负号,然后求元素和。 我们可以使用折半枚举的方法,枚举 nums 的前 n 个元素取正或取负的所有情况, 按取正的个数分组,并按照元素和排序。然后枚举 nums 的后 n 个元素取正或取负的所有情况, 然后去对应的组里二分找元素和最近的数,答案即为所有情况中最小的差值。 ''' class Solution: def minimumDifference(self, nums: List[int]) -> int: n = len(nums) // 2 left = [[] for _ in range(n+1)] right = [[] for _ in range(n+1)] def dfs(nums, res, i, c, record): if i == n: #bisect.insort(record[c],res) 这个太慢了,后排序更快一点 record[c].append(res) return dfs(nums, res+nums[i],i+1,c+1,record) dfs(nums,res-nums[i],i+1,c,record) dfs(nums[:n],0,0,0, left) dfs(nums[n:],0,0,0, right) ret = inf for i in range(n+1): lvs = left[i] rvs = right[i] lvs.sort() rvs.sort() lvs.append(inf) rvs.append(inf) k,j = 0,0 while k < len(lvs) and j < len(rvs) : t = lvs[k] - rvs[j] if abs(t) < ret: ret = abs(t) if t == 0: return 0 if t < 0: k += 1 else: j += 1 return ret