如何在数组中找到第一个非重复元素。 假设您只能为阵列的每个元素使用1位,并且时间复杂度应为O(n),其中n是数组的长度。 请确保我以某种方式对内存要求施加约束。也有可能的是,每个字符串元素只需要一个额外的位就可以完成。如果可能,请告诉我吗?
答案 0 :(得分:3)
我想说没有基于比较的算法,可以在O(n)中完成。因为你必须将数组的第一个元素与所有其他元素进行比较,第二个除了第一个之外的所有元素,第三个除了第一个之外的全部= Sum i = O(n ^ 2)。
(但这并不一定意味着没有更快的算法,请参阅排序:如果你是基于比较的话,有一个证据表明你不能比O(n log n)排序快 - 而且确实有一个更快:Bucket排序,可以在O(n)中完成。
编辑:在其他一条评论中,我谈到了哈希函数。我检查了一些关于它的事实,这里是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]);
有一些警告:
如何获得hash
。我做了一些关于完美哈希函数的研究。事实上,你可以在O(n)中生成一个。 (最小完美散列的最佳算法由George Havas等人 - 不确定这篇论文有多好,因为它声称为时间限制O(n)但是从非线性空间限制(这是计划)一个错误,我希望我不是唯一看到这个中的缺陷,但根据我所知道的所有理论计算机科学的时间是空间的上边界(因为你没有时间在更多的空间写))。但是我当他们说在O(n)中有可能时,请相信他们。
额外的空间 - 这里我没有看到解决方案。上面的论文引用了一些研究表明,你需要2.7位的完美哈希函数。使用额外的count
数组(可以缩短为状态:空+ 1个元素+超过1个元素),每个元素需要2个额外的位(如果您认为可以以某种方式与上述2.7结合使用,则为1.58) ,总计达到5位。
答案 1 :(得分:1)
这里我只假设字符串是字符串,只包含小字母,这样我就可以使用一个整数(32位),这样就可以使用26个字母表,每个字母表占一位。之前我想过采用256个元素的数组,但总共会有256 * 32位。每个元素32位。但最后我发现如果没有一个变量,我将无法做到。所以解决方案是这样的,只有一个整数(32位)用于26个字母:
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;
}
答案 2 :(得分:0)
此代码查找第一个重复元素。还没想到如果在同一个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 << "answer = " << answer ;
}
答案 3 :(得分: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]];
}
}
}
}