如何找到第一个非重复元素

How to find first non-repeating element?

本文关键字:元素 第一个 何找      更新时间:2023-10-16

如何查找数组中第一个不重复的元素。假设数组的每个元素只能使用1位,时间复杂度应为O(n),其中n为数组的长度。请确保我以某种方式对内存要求施加了约束。也有可能,字符串的每个元素只增加一个比特就无法实现。也请让我知道是否可能?

我想说没有基于比较的算法,可以在O(n)内完成。因为你必须比较数组的第一个元素和所有其他元素,第二个元素和除第一个元素外的所有元素,第三个元素和除第一个元素外的所有元素= Sum i = O(n^2)

(但这并不一定意味着没有更快的算法,参见排序:有证据表明,如果你是基于比较的,你的排序速度不能超过O(n log n) -确实有一个更快的:桶排序,它可以在O(n)内完成)。

EDIT:在另一个评论中,我说了一些关于哈希函数的事情。我检查了一些关于它的事实,这里是hashmap方法的想法:

  • 明显的方法是(在伪代码中):

    for (i = 0; i < maxsize; i++)
        count[i] = 0;
    for (i = 0; i < maxsize; i++) {
       h = hash(A[i]);
       count[h]++;
    }
    first = -1;
    for (i = 0; i < maxsize; i++)
       if (count[i] == 0) {
          first = i;
          break;
       }
    }
    for (i = 0; hash(A[i]) != first; i++) ;
    printf("first unique: " + A[i]); 
    
  • 有一些注意事项:

    1. 如何得到hash。我研究了一下完美哈希函数。实际上你可以在O(n)内生成一个。(最小完美哈希的最佳算法由George Havas等人编写。-不确定这篇论文有多好,因为它声称时间限制为O(n),但从非线性空间限制(这是计划错误,我希望我不是唯一看到这个缺陷的人,但根据所有理论计算机科学,我知道off时间是空间的上边界(因为你没有时间写更多的空间))。但我相信他们说在O(n)中是可能的。

    2. 额外的空间-这里我没有看到一个解决方案。上面的论文引用了一些研究,表明你需要2.7位才能得到完美的哈希函数。对于额外的count数组(您可以缩短为状态:Empty + 1 Element + More 1 Element),每个元素需要2个额外的位(如果您假设它可以以某种方式与上面的2.7结合在一起,则为1.58),这总计为额外的5位。

这里我只是假设字符串是字符串,只包含小字母,这样我就可以使用一个整数(32位),这样26个字母就足以每个字母取一个位。之前我想取一个包含256个元素的数组,但它总共有256*32位。每个元素32位。但最后我发现,如果没有一个变量,我将无法做到这一点。所以解决方案是这样的,26个字母只有一个整数(32位):

 int print_non_repeating(char* str)
 {
  int bitmap = 0, bitmap_check = 0;
  int length = strlen(str);
  for(int i=0;i<len;i++)
  {
   if(bitmap & 1<<(str[i] - 'a'))
     {
        bitmap_check = bitmap_check | ( 1 << (str[i] - 'a');
      }
   else 
      bitmap = bitmap | (1 << str[i] - 'a');
  }
  bitmap = bitmap ^ bitmap_check;
  i = 0;
  if(bitmap != 0)
  {
  while(!bitmap & (1<< (str[i])))
   i++;
  cout<<*(str+i);
   return 1;
  }
  else 
  return 0;
  }

您可以按照下面的示例尝试修改bucketsort。但是,您需要知道传递给firstNonRepeat方法的数组中的最大值。所以这个在O(n)处运行。对于基于比较的方法,理论上最快的(至少在排序方面)是O(n log n)。或者,您甚至可以使用修改版本的基数排序来完成此操作。

public class BucketSort{
    //maxVal is the max value in the array
    public int firstNonRepeat(int[] a, int maxVal){
        int [] bucket=new int[maxVal+1];
        for (int i=0; i<bucket.length; i++){
            bucket[i]=0;
        }
        for (int i=0; i<a.length; i++){
            if(bucket[a[i]] == 0) {
                bucket[a[i]]++;             
            } else {
                return bucket[a[i]];
            }
        }
    }
}

此代码查找第一个重复元素。我还没有弄清楚,在同一个for循环中,是否有可能找到不重复的元素,而不引入另一个for(以保持代码为O(n))。其他答案建议冒泡排序是O(n^2)

#include <iostream>
using namespace std;
#define max_size 10
int main()
{
    int numbers[max_size] = { 1, 2, 3, 4, 5, 1, 3, 4 ,2, 7};
    int table[max_size] = {0,0,0,0,0,0,0,0,0,0};
    int answer = 0, j=0;
  for (int i = 0; i < max_size; i++)
  {
    j = numbers[i] %max_size;
    table[j]++;
    if(table[j] >1)
    {
          answer = 1;
          break;
    }
 }
   std::cout << "answerswer = " << answer ;
}