查找数组Java的模式

时间:2018-11-12 23:07:09

标签: java arrays

我必须找到数组的模式。我有点尴尬地承认我已经坚持了一天。我想我已经考虑了一下-我的方法越来越长。我一直遇到的真正问题是,当没有一个模式(两个数字以相同的频率出现)时,我需要返回Double.NaN。

这是我尝试过的:

private double[] data = {1, 1, 2, 2, 2, 3, 4, 5, 5, 5, 5, 5, 6, 7, 7, 8, 8, 8, 8, 8, 9, 9, 9};

if(data.length != 0){

        double maxValue = -1;
        int maxCount = 0;
        for(int i = 0; i < data.length; i++) {
            int count = 0;
            for(int j = 0; j < data.length; j++) {
                if(data[j] == data[i]) {
                    count++;
                }
            }

            if(count > maxCount) {
                maxValue = (int) data[i];
                maxCount = count;
            }
        }
        return maxValue;

    }else{

        return Double.NaN;

    }

这实际上返回了模式,但是不能处理两种模式。这是我最近的尝试,但只完成了一半:

private double[] data = {1, 1, 2, 2, 2, 3, 4, 5, 5, 5, 5, 5, 6, 7, 7, 8, 8, 8, 8, 8, 9, 9, 9};

public void mode(){

    int[] frequency = new int[data.length];

    double[] vals = new double[data.length];

    for(int i = 0; i < data.length; i++){
        frequency[i] = occursNumberOfTimes(data[i]);
    }

    boolean uniform = false;

    for(int g = 0; g < frequency.length && !uniform; g++){
        if(frequency[0] != frequency[g]){
            uniform = false;
        }

    int[] arr = new int[frequency.length-1];

    for(int j = 1; j < frequency.length; j++){

        if(frequency[j] > frequency[j-1]){

            int mod = 0;

            for(int k = 0; k < arr.length; k++){
                if(k == j){
                    mod += 1;
                    arr[k] = frequency[k + mod];
                }else{
                    arr[k] = frequency[k + mod];    
                }
            }
        }
    }
    frequency = arr;
    }
}

private int occursNumberOfTimes(double value){

    int count = 0;

    for(int i = 0; i < data.length; i++){
        if(data[i] == value){
            count++;
        }
    }
    return count;
}

我在第二次尝试中迷路了,我只是无法弄清如何处理多种模式。我已经写出了自己的想法,但我只是不知道该怎么做。 我无法使用Arrays类中的任何内容,这就是我迷路的原因。

3 个答案:

答案 0 :(得分:1)

它必须高效吗?如果没有:

double maxValue = -1.0d;
int maxCount = 0;
for (int i = 0; i < data.length; ++i) {
    int currentValue = data[i];
    int currentCount = 1;
    for (int j = i + 1; j < data.length; ++j) {
        if (Math.abs(data[j] - currentValue) < epsilon) {
            ++currentCount;
        } 
    }
    if (currentCount > maxCount) {
        maxCount = currentCount;
        maxValue = currentValue;
    } else if (currentCount == maxCount) {
        maxValue = Double.NaN;
    }
}
System.out.println("mode: " + maxValue);

答案 1 :(得分:0)

您可以按照注释中的建议跟踪两个最常见的元素,但是另一种方法是保留一个布尔标志,该布尔标志指示当前最常见的元素是否唯一。然后:

  1. 对于每个数组元素e,请按当前方式获取其计数。
  2. 如果该计数大于当前最大值,则将最常见的元素(到目前为止可见)设置为e,并将“唯一”标志设置为true
  3. 否则,如果该计数等于当前的最大值,则将“唯一”标志设置为false

最后,如果“唯一”为true,则返回模式,否则返回NaN

答案 2 :(得分:0)

这是我漫长而愚蠢的解决方案。有用!这是获取模式的一种非常round回的方式,但我很高兴它能起作用。我使用了从一些评论中得到的建议,并以不同的方式看待它。几个小时令人沮丧,但这是:

public double mode2(){



    if(data.length != 0){

        int[] counts = new int[data.length];
        double[] vals = new double[data.length];

        for(int l = 0; l < data.length; l++){

            counts[l] = 1;

        }

        for(int i = 0; i < data.length; i++){

            for(int j = 0; j < data.length; j++){

                if((data[i] == data[j]) && (i != j)){

                    vals[i] = data[i];
                    counts[i] += 1;

                }

            }

        }

        for(int i = 0; i < data.length; i++){

            for(int j = 0; j < data.length; j++){

                if((vals[i] == vals[j]) && (i != j)){

                    vals[i] = 0;
                    counts[i] = 0;

                }

            }
        }

        int counter = 0;

        for(int k = 0; k < data.length; k++){

            if(counts[k] != 0){

                counts[counter] = counts[k];
                vals[counter] = vals[k];
                counter++;

            }

        }


        int[] compactCounts = new int[counter];
        double[] compactVals = new double[counter];

        for(int k = 0; k < counter; k++){

            if(counts[k] != 0){

                compactCounts[k] = counts[k];
                compactVals[k] = vals[k];

            }else{

                break;

            }

        }

        for(int g = 1; g < compactVals.length; g++){

            if(compactCounts[g] > compactCounts[g-1]){

                compactCounts[g-1] = 0;
                compactVals[g-1] = 0;

            }

        }

        for(int g = 0; g < compactVals.length-1; g++){

            if(compactCounts[g] > compactCounts[g+1]){

                compactCounts[g+1] = 0;
                compactVals[g+1] = 0;

            }

        }

        int counterTwo = 0;

        for(int k = 0; k < compactCounts.length; k++){

            if(compactCounts[k] != 0){

                compactCounts[counterTwo] = compactCounts[k];
                compactVals[counterTwo] = vals[k];
                counterTwo++;

            }

        }



        int[] compactCountsTwo = new int[counterTwo];
        double[] compactValsTwo = new double[counterTwo];

        for(int k = 0; k < counterTwo; k++){

            if(counts[k] != 0){

                compactCountsTwo[k] = compactCounts[k];
                compactValsTwo[k] = compactVals[k];

            }else{

                break;

            }
        }

        //now populated compactTwos

        //We're now setting some lesser values to 0

        for(int g = 1; g < compactValsTwo.length; g++){

            if(compactCountsTwo[g] > compactCountsTwo[g-1]){

                compactCountsTwo[g-1] = 0;
                compactValsTwo[g-1] = 0;

            }

        }


        //now setting other lesser values to 0


        for(int g = 0; g < compactValsTwo.length-1; g++){
            if(compactCountsTwo[g] > compactCountsTwo[g+1]){
                compactCountsTwo[g+1] = 0;
                compactValsTwo[g+1] = 0;

            }

        }


        //calling methods to shorten our arrays by dropping indexes populated by zeroes

        compactValsTwo = doubleTruncator(compactValsTwo);
        compactCountsTwo = intTruncator(compactCountsTwo);


        //now setting some lesser values to 0

        for(int g = 1; g < compactValsTwo.length; g++){

            if(compactCountsTwo[g] > compactCountsTwo[g-1]){

                compactCountsTwo[g-1] = 0;
                compactValsTwo[g-1] = 0;

            }

        }


        //now setting other lesser values to 0


        for(int g = 0; g < compactValsTwo.length-1; g++){
            if(compactCountsTwo[g] > compactCountsTwo[g+1]){
                compactCountsTwo[g+1] = 0;
                compactValsTwo[g+1] = 0;

            }

        }


        //calling methods to shorten our arrays by dropping indexes populated by zeroes

        compactValsTwo = doubleTruncator(compactValsTwo);
        compactCountsTwo = intTruncator(compactCountsTwo);


        if(compactValsTwo.length > 1){

            return Double.NaN;

        }else{

            return compactValsTwo[0];

        }

        }else{

            System.out.println("ISSUE");
            return Double.NaN;          
    }   
}


public double[] doubleTruncator(double[] a){

    int counter = 0;

    for(int k = 0; k < a.length; k++){

        if(a[k] != 0){

            a[counter] = a[k];
            counter++;

        }

    }

    double[] b = new double[counter];

    for(int i= 0; i < counter; i++){

        if(a[i] != 0){

            b[i] = a[i];

        }else{

            break;

        }

    }
    return b;

}


public int[] intTruncator(int[] a){

    int counter = 0;

    for(int k = 0; k < a.length; k++){

        if(a[k] != 0){

            a[counter] = a[k];
            counter++;

        }

    }

    int[] b = new int[counter];

    for(int i= 0; i < counter; i++){

        if(a[i] != 0){

            b[i] = a[i];

        }else{

            break;

        }

    }
    return b;

}

非常感谢所有提供帮助的人。我知道这不是很好(肯定不如@Perdi Estaquel的回答),但是我很高兴能够做到这一点。