查找数组在小于O(n ^ 2)内重复的次数

时间:2011-04-21 10:06:21

标签: java algorithm complexity-theory

我写的示例代码。但这是n ^ 2

int a[]={1,4,1,5,2,2,4,3,4,1};
int b[][]=new int[5][2];
int i,j,k=0,count=1;
boolean temp=false;
for(i=0;i<a.length;i++)
{
    for(j=0;j<5;j++)
    {
        if(a[i]==b[j][0])
        {   temp=true;
            b[j][1]++;
            break;
        }
    }

    if(temp==false)
    {
        b[k][0]=a[i];
        b[k][1]=1;
        k++;    
    }
    temp=false;
}
for(i=0;i<5;i++)
{
    for(j=0;j<1;j++)
    {
    System.out.println(b[i][j]+" is repeated "+b[i][j+1]+" times");
    }
}

9 个答案:

答案 0 :(得分:7)

这是伪代码的解决方案:

Map<Int, Int> histogram;
for(number in array) {
    histogram[number]++;
}

现在histogram[somenumber]包含数字在数组中的次数 - O(n)假设MapO(1)中查找项目

答案 1 :(得分:5)

选项1:牺牲记忆速度。

  • 使用像HashMap这样的数据结构来记录每个数字的频率。
  • 在O(n)时间内迭代建立频率计数,然后迭代整个HashMap或提取一个值。

选项2:排序

  • 排序,然后遍历整个排序结构或O(log n)以寻找特定值。
    • Quicksort平均n log n,O(n ^ 2)最坏情况,就位于内存中。
    • Mergesort或heapsort是O(n log n)但在排序期间占用额外的内存

答案 2 :(得分:3)

伪代码:

counts = dictionary default to 0

for each element in list:
    counts[element]+=1

O(n)的

答案 3 :(得分:2)

你应该使用eg。合并排序以对数组进行排序,然后使用简单的for循环遍历整个数组来计算重复次数。

合并排序有n * log(n),而for循环找到重复也很快。

答案 4 :(得分:1)

快速排序算法应该比O(n ^ 2)快得多,然后是一个组,即O(n)应该仍然比O(n ^ 2)快。

因此,在伪代码中:

    group (sort [1,2,3,3,2,1])   =>   [(1,2), (2,2), (3,2)] 

答案 5 :(得分:1)

您可以通过创建另一个数据结构(如地图)在O(n)时间内完成。 例如:int a [] = {1,4,1,5,2,2,4,3,4,1};

Map<Integer, Integer> map = new HashMap<Integer, Integer>();

for(int i = 0; i < a.length ; i++)
{
    if(map.containsKey(a[i]))
    {
        map.put(a[i], map.get(a[i])+1);
    }
    else
    {
        map.put(a[i], 1);
    }
}

System.out.print(map);

结果:{1 = 3,2 = 2,3 = 1,4 = 3,5 = 1}

答案 6 :(得分:0)

为什么使用2-dim阵列?如果已知您的数字在1..5范围内,请使用数字索引:

    int a[] = {1,4,1,5,2,2,4,3,4,1};
    int b[] = new int[5];

    for (int n : a)
        ++b[n-1];

    for (int j=0; j < 5; ++j)
        System.out.println (j + " is repeated " + b [j-1] + " times");
  • 不要过早声明变量,也不要重复使用变量。您将忘记删除未使用的变量(计数),并难以分析代码。
  • 使用改进的for:loop。
  • 在头部声明计数器 - 这是允许的原因:for(int i = ...)以及为什么我在块外不可见。它不贵。不,不是。看一下字节码。

答案 7 :(得分:0)

如果您可以更改现有阵列,则可以执行此操作。它的O(n log(n))并不会创建新对象。 (如果你无法改变原作,你可以克隆它。)它比维护Map更有效。 ;)

int a[] = {1, 4, 1, 5, 2, 2, 4, 3, 4, 1};

Arrays.sort(a);
int last = a[0];
int count = -1; 
for (int i : a) {
    if (i == last) {
        count++;
        continue;
    }
    System.out.println("Number " + last + " found " + count + " times.");
    count = 1;
    last = i;
}
System.out.println("Number " + last + " found " + count + " times.");

打印

Number 1 found 3 times.
Number 2 found 2 times.
Number 3 found 1 times.
Number 4 found 3 times.
Number 5 found 1 times.

答案 8 :(得分:0)

在这种情况下,

将O(n ^ 2)简化为O(n * log n)很简单:

  1. 使用heapsort / quicksort排序数字... O(n * log n)
  2. 遍历数组一次并计算唯一元素并获取其计数... O(n)
  3. 保持高度平衡的树,数字作为键以及出现次数是另一个想法,它将给出O(n * log n)。我没有看到O(n)解决方案没有使用大多数语言中容易获得的数据结构的散列表。