基于this逻辑作为对不同(类似)问题的SO的回答,为了在O(N)时间复杂度中删除数组中的重复数字,我在C中实现了该逻辑,如图所示下面。但是我的代码的结果不会返回唯一的数字。我试过调试,但无法得到它背后的逻辑来解决这个问题。
int remove_repeat(int *a, int n)
{
int i, k;
k = 0;
for (i = 1; i < n; i++)
{
if (a[k] != a[i])
{
a[k+1] = a[i];
k++;
}
}
return (k+1);
}
main()
{
int a[] = {1, 4, 1, 2, 3, 3, 3, 1, 5};
int n;
int i;
n = remove_repeat(a, 9);
for (i = 0; i < n; i++)
printf("a[%d] = %d\n", i, a[i]);
}
1]上述代码中删除重复项的内容有误。
2]针对此问题的任何其他O(N)或O(NlogN)解决方案。它的逻辑?
答案 0 :(得分:2)
INT_MAX
)。仍以O(n log n)为界。
答案 1 :(得分:1)
您将需要两个循环,一个用于检查源,另一个用于检查目标数组中的每个项目。
你不会得到O(N)。
[编辑] 您链接的文章建议使用排序输出数组,这意味着在输出数组中搜索重复项可以是二进制搜索...即O(LogN)。
答案 2 :(得分:1)
您的代码似乎要求输入已排序。使用未分类的输入时,您的代码将不会删除所有重复项(仅限相邻项)。
答案 3 :(得分:1)
如果预先知道整数的数量并且小于你拥有的内存量,你就可以得到O(N)解决方案。使用辅助存储来确定一个唯一的整数,然后输出另一个以输出唯一值。
下面的代码是用Java编写的,但希望你能理解。
int[] removeRepeats(int[] a) {
// Assume these are the integers between 0 and 1000
Boolean[] v = new Boolean[1000]; // A lazy way of getting a tri-state var (false, true, null)
for (int i=0;i<a.length;++i) {
v[a[i]] = Boolean.TRUE;
}
// v[i] = null => number not seen
// v[i] = true => number seen
int[] out = new int[a.length];
int ptr = 0;
for (int i=0;i<a.length;++i) {
if (v[a[i]] != null && v[a[i]].equals(Boolean.TRUE)) {
out[ptr++] = a[i];
v[a[i]] = Boolean.FALSE;
}
}
// Out now doesn't contain duplicates, order is preserved and ptr represents how
// many elements are set.
return out;
}
答案 4 :(得分:1)
您的代码仅检查数组中的项是否与其前一个项相同。
如果您的数组开始排序,那将起作用,因为特定数字的所有实例都是连续的。
如果你的数组没有排序开始,那将无法工作,因为特定数字的实例可能不连续,所以你必须查看所有前面的数字以确定是否还有人看过。
要在O(N log N)时间内完成工作,您可以对数组进行排序,然后使用已有的逻辑从已排序的数组中删除重复项。显然,这只有在你重新安排数字时才有用。
如果您想保留原始订单,可以使用类似哈希表或位设置的内容来跟踪是否已经看到某个数字,并且当/它还没有时,只将每个数字复制到输出中被人看见了。为此,我们改变您的当前状态:
if (a[k] != a[i])
a[k+1] = a[i];
类似于:
if (!hash_find(hash_table, a[i])) {
hash_insert(hash_table, a[i]);
a[k+1] = a[i];
}
如果您的数字都在相当窄的范围内,或者您希望这些值是密集的(即,大多数值都存在),您可能希望使用位集而不是哈希表。这只是一个位数组,设置为零或一个,以指示是否已经看到一个特定的数字。
另一方面,如果您更关心复杂性的上限而不是普通情况,则可以使用基于树的平衡集合而不是哈希表。这通常会使用更多内存并且运行速度更慢,但其预期的复杂性和最差情况复杂性基本相同(O(N log N))。在最坏的情况下,典型的哈希表从常数复杂度退化为线性复杂度,这将使您的整体复杂度从O(N)变为O(N 2 )。
答案 5 :(得分:0)
你的逻辑错了,所以代码也错了。在编码之前自己做你的逻辑。 我建议采用O(NlnN)方式修改heapsort。 使用heapsort,我们从[i]加入到[n],找到最小值并用[i]替换它,对吧? 所以现在是修改,如果最小值与[i-1]相同,那么交换最小值和[n],将数组项的数量减少1。 它应该以O(NlnN)方式完成。
答案 6 :(得分:0)
您的代码仅适用于特定情况。显然,您正在检查相邻值,但重复值可能出现在数组中的任何位置。因此,这是完全错误的。