【问题标题】:Given an array of positive integers. Divide it into 2 arrays where avg of each array is same给定一个正整数数组。将其分成 2 个数组,其中每个数组的 avg 相同
【发布时间】:2018-04-18 20:20:09
【问题描述】:

例子:

[1,2,4,5] 输出将是 [1,5] 和 [2,4]

所以这是我尝试过的,但是代码中断在某一点需要帮助来做出决策。从下面的代码 if(avgArr1 是我决定哪些需要是源数组,它需要成为插入和删除元素的目标数组。此条件不可靠,会清空其中一个数组。

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);
    }
}

【问题讨论】:

  • 这不一定适用于每个数字数组...例如,不可能将[1, 2, 5][1, 2, 1000, 10000] 划分为均值的子集。在这种情况下,解决方案应该怎么做?
  • 在没有解决方案的情况下,它应该返回未找到的解决方案,尽管在上面的代码中没有处理。
  • 顺便说一句,IntStream 有一个 average 方法,所以如果你确定数组永远不会为空,那么你可以使用 double avgArr1 = IntStream.of(arr1).average().getAsDouble(); 否则使用可选方法来决定在空数组的情况下采取适当的行动。避免IntStream.of(arr1).sum()/arr1.length;

标签: java algorithm java-8 dynamic-programming


【解决方案1】:

这个问题可以用动态规划来解决。制作一个大小为OverallSum 的表格。用所有可能的子集和填充它,还记录项目数和用于计算每个总和的最后一个项目。

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

例如[1, 2, 5, 6] A = 3.5 = 7/2 所以检查 sum 7 是否可能由 由两个项目组成

【讨论】:

    【解决方案2】:

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

    如果

    a / b = c / d
    

    然后

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

    所以您正在寻找的是一个分区,其中每个部分的总和是整个列表平均值的倍数。我们可以分而治之,至少将我们的子集和搜索拆分为仅由小于整个列表平均值的元素或仅由大于整个列表平均值的元素组成的那些。

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

    否则,让shsl 分别为所有高于A 的元素子集和所有低于A 的元素子集的总和;和khkl 这些子集各自的基数。那么:

    (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
    

    【讨论】:

      猜你喜欢
      • 2018-02-20
      • 2020-07-26
      • 1970-01-01
      • 2012-10-04
      • 1970-01-01
      • 2013-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多