快速查找数组中元素的数量

时间:2012-03-05 07:14:24

标签: java arrays performance search

我有一个数组,大小可以达到10000.它只有1/2/3/4。我需要找到阵列中有多少1s,2s,3s和4s。这样做的最快方法是什么?我的使用语言是Java。我的代码 -

for(int i=0; i<myArray.length;i++){
            int element = myArray[i];
            if(element == 1){
                onesCount++;
            }
            else if(element == 2){
                twosCount++;
            }
            else if(element == 3){
                threesCount++;
            }
            else
                foursCount++;
}

我希望有一个很好的解决方案。

8 个答案:

答案 0 :(得分:7)

int count[5]; //initialize this to 0
for(int i = 0; i<n; i++)
{
count[array[i]]+=1;
}

答案 1 :(得分:2)

您将拥有阵列条目的单独计数器。在找到新的匹配数字时,每个都会增加,因此您必须至少访问每个索引,也就是说您将在O(n)时间内使用算法。可以首选switch语句而不是多个if-else语句:

int[] array = new int[10000];
// ... populate array
int[] counters = new int[4];

for (int i = 0; i < array.length; i++)
{
    int temp = array[i];
    switch (temp) {
    case 1:
        counters[0]++;
        break;
    case 2:
        counters[1]++;
        break;
    case 3:
        counters[2]++;
        break;
    case 4:
        counters[3]++;
        break;
    default:
        // to do.
    }
}

答案 2 :(得分:2)

没有比你更好的解决方案。可以更灵活,但不会更快。一切都必须至少完成整个阵列的单次传递。

性能优化的唯一区域是避免执行此操作,例如在更新阵列时跟踪计数器。如果值得这么麻烦(可能不是)取决于你需要多久做一次,数组有多大,以及你还需要做些什么。

答案 3 :(得分:1)

如果您使用的是Java 7,则可以使用Fork/Join Framework。 复杂性仍然是O(n)......但对于大型数组来说可能更快

答案 4 :(得分:0)

您可以使用一次通过数组来完成此操作。

只需拥有一个包含四个元素的数组,每个元素代表一个值(1/2/3/4),对于原始数组中的每个元素,您可以增加“count”数组中相应位置的计数。 这将使它成为O(n)。

答案 5 :(得分:0)

如果您可以使用地图或自定义类。如果你不能,你必须遍历整个数组。如果你现在没有遇到性能问题,我会尽量做迭代。

答案 6 :(得分:0)

如果开关版本(deporter)或noMAD的版本不是最好的,试试这个:

for (int i = 0; i < myArray.length; i++) {
    int element = myArray[i];
    if (element > 2) {
        if (element == 4) {
            foursCount++;
        } else 
            threesCount++;
    } else {
        if (element == 2) 
            twosCount++;
        else 
            onesCount++; 
    }
}

它可以节省少量的比较。但这取决于真实的数据。如果您对数据很幸运,那么直接版本可能会做得更好。

除此之外,使用并行性总是值得尝试大数据。

答案 7 :(得分:0)

我认为你不会比这更快:

final int[] counts = new int[5];
final int length = array.length - 1;
for (int i = 0; i < length; i++) {
   counts[array[i]]++;
}

请注意,在 for 循环中,未引用 array.length 。它被放入一个局部的final int中,这避免了在每次迭代中取消引用array.length。

我对此方法进行了基准测试,该方法使用了switch..case语句,只使用了本地堆栈变量:

    int count1 = 0;
    int count2 = 0;
    int count3 = 0;
    int count4 = 0;

    for (int i = array.length - 1; i >= 0; i--) {
        switch (array[i]) {
        case 1:
            count1++;
            break;
        case 2:
            count2++;
            break;
        case 3:
            count3++;
            break;
        case 4:
            count4++;
            break;
        }
    }

结果是第一种方法需要17300纳秒,而switch..case方法需要79800纳秒。 [更新:忘记将纳秒除以10.我每次运行10次。]

注意:在确定基准测试之前,我首先警告了VM。