拼图:在数组中找出重复的元素

时间:2010-10-08 02:23:54

标签: arrays

数组的大小为n。除了两个元素外,数组中的所有元素在[0,n-1]的范围内是不同的。找出重复元素而不使用具有恒定时间复杂度的额外临时数组。

我试着用这样的o(n)。

   a[]={1,0,0,2,3};
    b[]={-1,-1,-1,-1,-1};
    i=0;
    int required;
    while(i<n)
    {
      b[a[i]]++;
      if(b[a[i]==1)
        required=a[i];
    }
    print required;

如果对数字范围没有约束,即允许超出范围。是否可以获得没有临时数组的o(n)解。

9 个答案:

答案 0 :(得分:3)

XOR将所有元素放在一起,然后XOR将结果与XOR([0..n-1])放在一起。

这会给你missing XOR repeat;自missing!=repeat起,missing XOR repeat中至少设置了一位。

选择其中一个设定位。再次迭代所有元素,并且仅设置该位的XOR个元素。然后从1迭代到n-1XOR那些具有该位设置的数字。

现在,该值是重复值或缺失值。扫描该值的元素。如果你找到它,它就是重复的元素。否则,它是缺失值,因此XORmissing XOR repeat

答案 1 :(得分:2)

  1. 查看第一个和最后一个数字
  2. 计算不重复的数组元素的SUM(1)(就像你知道1 ... 5 = 1 + 2 + 3 + 4 + 5 = 15之和。称之为SUM(1))。正如AaronMcSmooth指出的那样,公式为Sum(1, n) = (n+1)n/2
  3. 计算给定给您的数组中元素的SUM(2)。
  4. 减去SUM(2) - SUM(1)。哇!结果是重复的数字(如果给定的数组是1,2,3,4,5,3,SUM(2)将是18. 18 - 15 = 3.所以3是重复的。)
  5. 祝你好运!

答案 2 :(得分:2)

选择两个不同的随机索引。如果这些索引处的数组值相同,则返回true。

这在恒定的时间内运作。作为奖励,你得到正确答案,概率为2 / n * 1 /(n-1)。

答案 3 :(得分:1)

O(n)没有临时数组。

a[]={1,0,0,2,3};
i=0;
int required;
while(i<n)
{
  a[a[i] % n] += n;
  if(a[a[i] % n] >= 2 * n)
    required = a[i] % n;
}
print required;

(当然假设n

答案 4 :(得分:1)

此示例可用于int,char和string。

char[] ch = { 'A', 'B', 'C', 'D', 'F', 'A', 'B' };
Dictionary<char, int> result = new Dictionary<char, int>();
foreach (char c in ch)
{
   if (result.Keys.Contains(c))
   {
       result[c] = result[c] + 1;
   }
   else
   {
       result.Add(c, 1);
   }
}
foreach (KeyValuePair<char, int> pair in result)
{
   if (pair.Value > 1)
   {
       Console.WriteLine(pair.Key);
   }
}
Console.Read();

答案 5 :(得分:0)

懒惰解决方案:java.util.Set逐个将元素放到add(E),直到add(E) == false。

抱歉没有时间。 HashMap:O(N),TreeSet:O(lgN * N)。

答案 6 :(得分:0)

构建查找表。抬头。完成。

非临时阵列解决方案:

构建门阵列硬件的查找,调用。

答案 7 :(得分:0)

我能做的最好的事情是及时O(n log n)O(1)空间:

基本思想是通过0执行 n-1的二进制搜索,在每一步传递整个n元素数组。

  1. 最初,请i=0j=n-1k=(i+j)/2
  2. 在每次遍历数组时,将值在ik范围内的元素相加,并计算此范围内元素的数量。
  3. 如果总和等于(k-i)*(k-i+1)/2 + i*(k-i+1),则范围ik既没有重复也没有省略值。如果元素的数量小于k-i+1,则范围具有省略的值,但不包含重复。在任何一种情况下,请将i替换为k+1,将k替换为(i+j)/2的新值。
  4. 否则,请将jk替换为k的新值。
  5. 如果(i+j)/2,请转到2。
  6. 算法终止于i!=j,并且两者都等于重复元素。

    (注意:我编辑了这个以简化它。旧版本可能找到了复制或省略的元素,并且如果初始搜索出现了省略的值,则必须使用Vlad的差异技巧来找到副本。)

答案 8 :(得分:0)

基于@ sje的回答。最坏的情况是2次通过阵列,没有额外的存储,非破坏性。

O(n)没有临时数组。

a[]={1,0,0,2,3};
i=0;
int required;
while (a[a[i] % n] < n)    
   a[a[i++] % n] += n;

required = a[i] % n;
while (i-->0)
   a[a[i]%n]-=n;

print required;

(当然假设n