给出一组正整数。将其划分为2个数组,其中每个数组的avg相同

时间:2018-04-18 20:20:10

标签: java algorithm java-8 dynamic-programming

示例:

[1,2,4,5]输出为[1,5]和[2,4]

所以这就是我尝试的但是代码断点在某一点上需要帮助决策。从下面的代码如果(avgArr1< avgArr2){是我决定哪个需要的点是要插入和删除元素的目标数组的源数组。这种情况不可靠,并排空其中一个阵列。

package test;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.IntStream;

public class ArrayAvg {
    static int[] arr1;
    static int[] arr2;
    public Map<String,int[]> swap(int[] src,int[] dest,int num,boolean swapLeft){
        Map<String,int[]> arrMap = new HashMap<String,int[]>();
        System.out.println("num"+num);
        ///System.out.println(Arrays.toString(src));
        ///System.out.println(Arrays.toString(dest));
        int[] tempL;
        int[] tempR;
        int myNumber = num;
        int distance = Math.abs(src[0] - myNumber);
        int idx = 0;
        for(int c = 1; c < src.length; c++){
            int cdistance = Math.abs(src[c] - myNumber);
            if(cdistance < distance){
                idx = c;
                distance = cdistance;
            }
        }
        int theNumber = src[idx];
        System.out.println("the num"+theNumber);
        if(swapLeft){
            tempL= new int[dest.length+1];
            tempR= new int[src.length-1];
            tempR = Arrays.stream( src ).filter( value -> value != theNumber ).toArray();
            //System.out.println(Arrays.toString(tempR));
            tempL = Arrays.copyOf(dest, dest.length+1);//Range(dest, 0, src.length);
            tempL[tempL.length-1] = theNumber;
            //*/System.arraycopy(dest, 0, tempL, 1, 2);*/
            //System.out.println(tempL.length+1);
            //System.out.println(Arrays.toString(tempL));
            arr1 = tempL;
            arr2 = tempR;
        }else{
            tempL= new int[src.length-1];
            tempR= new int[dest.length+1];
            tempR = Arrays.stream( src ).filter( value -> value != theNumber ).toArray();
            tempL = Arrays.copyOfRange(dest, 0, src.length);
            tempL[tempL.length-1] = num;
            arr1 = tempR;
            arr2 = tempL;
        }
        /*dest = tempL;
        src = tempR;*/
        arrMap.put("arr1", arr1);
        arrMap.put("arr2", arr2);
        //System.out.println(Arrays.toString(tempL));
        //System.out.println(Arrays.toString(arr1));
        System.out.println(Arrays.toString(arr1));
        System.out.println(Arrays.toString(arr2));
        //System.arraycopy(temp, 0, dest, 0, temp.length);
        return  arrMap;
    }
    public void printArr(int[] arr,int[] arr1,int[] arr2){
        Arrays.sort(arr1);
        Arrays.sort(arr2);

        double avgArr1 = IntStream.of(arr1).sum()/arr1.length;
        double avgArr2 = IntStream.of(arr2).sum()/arr2.length;
        while(avgArr1 != avgArr2){
            int arrAvg = (int) (avgArr1 + avgArr2)/2;
            int nearestValue = (arrAvg/2);
            System.out.println(arrAvg);
            Map<String,int[]> res;
            if(avgArr1 < avgArr2){
                res = swap(arr2,arr1,nearestValue,true);
            }else{
                res = swap(arr1,arr2,nearestValue,false);
            }
            arr1 = res.get("arr1");
            arr2 = res.get("arr2");
            avgArr1 = IntStream.of(arr1).sum()/arr1.length;
            avgArr2 = IntStream.of(arr2).sum()/arr2.length;
            Arrays.sort(arr1);
            Arrays.sort(arr2);
        }
        //System.out.println(Arrays.toString(arr1));
        //System.out.println(Arrays.toString(arr2));
    }
    public static void main(String args[]){
        int [] intarr = {1,2,5,4};
        Arrays.sort(intarr);
        //ArrayAvg.printArr(intarr); 
        arr1 = Arrays.copyOfRange(intarr, 0, intarr.length/2);
        //System.out.println(Arrays.toString(arr));
        arr2 = Arrays.copyOfRange(intarr, (intarr.length/2), intarr.length);
        new ArrayAvg().printArr(intarr,arr1,arr2);
        //System.out.println(intarr);
    }
}

2 个答案:

答案 0 :(得分:0)

这个问题可以通过动态编程来解决。制作一张尺寸为OverallSum的桌子。填写所有可能的子集总和,记录项目数量和用于计算每笔金额的最后一项。

让整个数组的平均值为A = P/Q(理性值,GCD(P,Q)=1)。现在检查是否可以从P, 2P, 3P... kP项创建总和Q, 2Q, 3Q...kQ。如果是,请展开总和以获得构成此总和的项目

例如[1, 2, 5, 6] A = 3.5 = 7/2因此,请检查总和7 是否可能由两个项目组成

答案 1 :(得分:0)

如果您只对两个部分的平均值相同的解决方案感兴趣,则意味着这两个部分必须具有(1)仅作为成员的目标平均值或(2)低于平均值的一组和一组高于平均数的人。

此外,如果

a / b = c / d

然后

a / b = (a + c) / (b + d)

所以你要找的是一个分区,每个部分的总和是整个列表平均值的倍数。我们可以划分和征服至少将我们的子集和搜索分割成那些小于或大于元素大于整个列表平均值的独有元素。

A成为整个列表的平均值。如果列表中的任何元素等于A,则将任意数量的元素拆分为一个部分将构成有效的解决方案。

否则,让shsl为高于A的元素子集的总和,以及小于A的元素子集的总和,分别;以及khkl这些子集&#39;各自的基数。然后:

(sh + sl) / (kh + kl) = A

因此,给定低于A(sl, kl)的元素子集的任何和和基数,高于A的元素的匹配元组必须等于常量:

sh = A * (kh + kl) - sl

sh - A * kh = A * kl - sl

我们可以存储和查找sh - A * kh(对于较低的元组也是如此)。

实施例

[1,2,4,5]
A = 3

[1,5][2,4]中的任何一个都会通知我们存在解决方案。我们只需要找到一个

sh - A * kh  =  A * kl - sl

5  - 3 * 1   =  3 * 1  - 1
4  - 3 * 1   =  3 * 1  - 2