如何找到第一个非重复元素
How to find first non-repeating element?
如何查找数组中第一个不重复的元素。假设数组的每个元素只能使用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]);
-
有一些注意事项:
-
如何得到
hash
。我研究了一下完美哈希函数。实际上你可以在O(n)内生成一个。(最小完美哈希的最佳算法由George Havas等人编写。-不确定这篇论文有多好,因为它声称时间限制为O(n),但从非线性空间限制(这是计划错误,我希望我不是唯一看到这个缺陷的人,但根据所有理论计算机科学,我知道off时间是空间的上边界(因为你没有时间写更多的空间))。但我相信他们说在O(n)中是可能的。 -
额外的空间-这里我没有看到一个解决方案。上面的论文引用了一些研究,表明你需要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 ;
}
- 为什么它只打印双链接列表的第一个值,而我的程序却崩溃了
- std::find,返回所有找到的值的替代方法,而不仅仅是存在重复的向量的第一个值
- 为什么在 std::map 上移动无法将元素从一个映射移动到另一个映射
- 如何仅读取文本文件中的第一个值
- 在C++中,如何在第一个"system()"结束后执行第二个"system()"?
- 查找不在标准中的第一个值::设置<int>最小-最大值
- C++:忽略第一个 cin.ignore 之后的输入
- 在C++中打印多个矢量的第一个值
- C++去除前x个元素的有效方法,在不改变向量大小的情况下将第x+1个元素推到第一个
- C++第一个cout将不会打印
- 我们可以在第一个else-if条件结束后使用另一个else-if条件吗
- OpenGL:第二个VBO破坏了第一个VBO
- 为什么第一个Dynamic_cast没有投射到基类?
- OpenGL 2D游戏只绘制第二个精灵纹理而不是第一个
- C++ 为什么程序只读取第一个值
- 在我的第一个C++程序中需要一些帮助(简单)
- 将顶部堆栈元素传输到第二个堆栈的第一个
- 获取不等于特定值的向量的第一个N元素
- 如何将std ::映射的第一个N元素复制到另一个地图
- 如何在C中获取char阵列的第一个X元素?提升效果是否有改进的方法