列表

详情


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

给你一个长度为 2 * n 的整数数组。你需要将 nums 分成 两个 长度为 n 的数组,分别求出两个数组的和,并 最小化 两个数组和之 差的绝对值 。nums 中每个元素都需要放入两个数组之一。

请你返回 最小 的数组和之差。

 

示例 1:

example-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:

example-3

输入:nums = [2,-1,0,4,-2,-9]
输出:0
解释:最优分组方案是分成 [2,4,-9] 和 [-1,0,-2] 。
数组和之差的绝对值为 abs((2 + 4 + -9) - (-1 + 0 + -2)) = 0 。

 

提示:

原站题解

去查看

上次编辑到这里,代码来自缓存 点击恢复默认模板
class Solution { public: int minimumDifference(vector<int>& nums) { } };

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

上一题