2022-01-18:将数组分成两个数组并最小化数组和的差。 给你一个长度为 2 * n 的整数数组。你需要将 nums 分成 两个 长度为 n 的数组,分别求出两个数组的和,并 最小化 两个数组和之

Posted 福大大架构师每日一题

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2022-01-18:将数组分成两个数组并最小化数组和的差。 给你一个长度为 2 * n 的整数数组。你需要将 nums 分成 两个 长度为 n 的数组,分别求出两个数组的和,并 最小化 两个数组和之相关的知识,希望对你有一定的参考价值。

2022-01-18:将数组分成两个数组并最小化数组和的差。
给你一个长度为 2 * n 的整数数组。你需要将 nums 分成 两个 长度为 n 的数组,分别求出两个数组的和,并 最小化 两个数组和之 差的绝对值 。nums 中每个元素都需要放入两个数组之一。
请你返回 最小 的数组和之差。
输入:nums = [3,9,7,3]。
输出:2。
解释:最优分组方案是分成 [3,9] 和 [7,3] 。
数组和之差的绝对值为 abs((3 + 9) - (7 + 3)) = 2 。
力扣2035。

答案2022-01-18:

分治法。
arr -> 8 0 1 2 3 4 5 6 7
process(arr, 0, 4) [0,4)
process(arr, 4, 8) [4,8)
arr -> 8 0 1 2 3 4 5 6 7
process(arr, 0, 4) [0,4)
process(arr, 4, 8) [4,8)
arr[index…end-1]这个范围上,去做选择
pick挑了几个数!
sum挑的这些数,累加和是多少!
map记录结果
HashMap<Integer, TreeSet> map
key -> 挑了几个数,比如挑了3个数,但是形成累加和可能多个!
value -> 有序表,都记下来!
整个过程,纯暴力!2^15 -> 3万多,纯暴力跑完,依然很快!

代码用golang编写。代码如下:

package main

import (
    "fmt"
    "math"
    "sort"
)

func main() 
    ret := minimumDifference([]int3, 9, 7, 3)
    fmt.Println(ret)


func minimumDifference(arr []int) int 
    size := len(arr)
    half := size >> 1
    //HashMap<Integer, TreeSet<Integer>> lmap = new HashMap<>();
    lmap := make(map[int]map[int]struct)
    process(arr, 0, half, 0, 0, lmap)
    //HashMap<Integer, TreeSet<Integer>> rmap = new HashMap<>();
    rmap := make(map[int]map[int]struct)
    process(arr, half, size, 0, 0, rmap)
    sum := 0
    for _, num := range arr 
        sum += num
    
    ans := math.MaxInt64
    for leftNum, _ := range lmap 
        for leftSum, _ := range lmap[leftNum] 
            rr := rmap[half-leftNum]
            //模拟treeset
            rarr := make([]int, 0)
            for r, _ := range rr 
                rarr = append(rarr, r)
            
            sort.Ints(rarr)
            ri := NearestIndex2(rarr, (sum>>1)-leftSum)
            rightSum := 0
            if ri != -1 
                rightSum = rarr[ri]
                pickSum := leftSum + rightSum
                restSum := sum - pickSum
                //ans = Math.min(ans, restSum - pickSum);
                if ans > restSum-pickSum 
                    ans = restSum - pickSum
                
            
        
    
    return ans


// arr -> 8   0 1 2 3      4 5 6 7
// process(arr, 0, 4)  [0,4)
// process(arr, 4, 8)  [4,8)
// arr[index....end-1]这个范围上,去做选择
// pick挑了几个数!
// sum挑的这些数,累加和是多少!
// map记录结果
// HashMap<Integer, TreeSet<Integer>> map
// key -> 挑了几个数,比如挑了3个数,但是形成累加和可能多个!
// value -> 有序表,都记下来!
// 整个过程,纯暴力!2^15 -> 3万多,纯暴力跑完,依然很快!
func process(arr []int, index int, end int, pick int, sum int, map0 map[int]map[int]struct) 
    if index == end 
        if _, ok := map0[pick]; !ok 
            map0[pick] = make(map[int]struct)
        
        map0[pick][sum] = struct
     else 
        process(arr, index+1, end, pick, sum, map0)
        process(arr, index+1, end, pick+1, sum+arr[index], map0)
    


// 在arr上,找满足<=value的最右位置
func NearestIndex2(arr []int, v int) int 
    L := 0
    R := len(arr) - 1
    index := -1 // 记录最右的对号
    for L <= R 
        mid := L + (R-L)>>1
        if arr[mid] <= v 
            index = mid
            L = mid + 1
         else 
            R = mid - 1
        
    
    return index

执行结果如下:


左神java代码

moonfdd

以上是关于2022-01-18:将数组分成两个数组并最小化数组和的差。 给你一个长度为 2 * n 的整数数组。你需要将 nums 分成 两个 长度为 n 的数组,分别求出两个数组的和,并 最小化 两个数组和之的主要内容,如果未能解决你的问题,请参考以下文章

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

将数组分成两个数组并最小化数组和的差(折半搜索+二分)

归并排序

图中是把二十个字节的数组分成正数组和负数组,并分别计算两个数组中数据的个数的汇编程序。请画出程序流

将具有相同或不同长度的2个不同整数数组合并为一个大数组,并将它们从最小到最大排序

排序算法——快排思想