我有一个可能包含重复元素的数组(元素的两个以上重复)。我想知道是否有可能找到并删除数组中的重复项:
P.S :这不是主页工作问题
在雅虎的技术采访中被问到我的朋友
答案 0 :(得分:8)
对源数组进行排序。找到相等的连续元素。 (即std::unique
在C ++中的作用)。总复杂度为N lg N,如果输入已经排序,则仅为N.
要删除重复项,您可以在线性时间内从数组中较早的元素复制数组中较晚的元素。只需保留指向容器新逻辑端的指针,并在每一步将下一个不同元素复制到该新逻辑端。 (再次,与std::unique
完全一样(事实上,为什么不下载 an implementation of std::unique
并完全按照它做的做法?:P))
答案 1 :(得分:5)
O(NlogN):用一个副本对连续的相同元素进行排序和替换。
O(N 2 ):运行嵌套循环以将每个元素与数组中的其余元素进行比较,如果找到重复,则将副本与数组末尾的元素交换并减少数组大小为1.
答案 2 :(得分:3)
对复杂性没有限制。
所以这是小菜一碟。
// A[1], A[2], A[3], ... A[i], ... A[n]
// O(n^2)
for(i=2; i<=n; i++)
{
duplicate = false;
for(j=1; j<i; j++)
if(A[i] == A[j])
{duplicate = true; break;}
if(duplicate)
{
// "remove" A[i] by moving all elements from its left over it
for(j=i; j<n; j++)
A[j] = A[j+1];
n--;
}
}
答案 3 :(得分:2)
在二次时间内保留列表现有顺序的就地重复删除:
for (var i = 0; i < list.length; i++) {
for (var j = i + 1; j < list.length;) {
if (list[i] == list[j]) {
list.splice(j, 1);
} else {
j++;
}
}
}
诀窍是在i + 1
上启动内循环,而在删除元素时不增加内部计数器。
代码是JavaScript,splice(x, 1)
删除了x
的元素。
如果订单保存不是问题,那么您可以更快地完成:
list.sort();
for (var i = 1; i < list.length;) {
if (list[i] == list[i - 1]) {
list.splice(i, 1);
} else {
i++;
}
}
哪个是线性的,除非你计算排序,你应该这样,所以它是排序的顺序 - 在大多数情况下是n×log(n)。
答案 4 :(得分:1)
在函数式语言中,您可以在一次传递中将排序和统一(这是一个真正的单词吗?)结合起来。 我们采用标准的快速排序算法:
- Take the first element of the input (x) and the remaining elements (xs)
- Make two new lists
- left: all elements in xs smaller than or equal to x
- right: all elements in xs larger than x
- apply quick sort on the left and right lists
- return the concatenation of the left list, x, and the right list
- P.S. quick sort on an empty list is an empty list (don't forget base case!)
如果您只想要唯一条目,请替换
left: all elements in xs smaller than or equal to x
带
left: all elements in xs smaller than x
这是一次通过O(n log n)算法。
F#中的示例实现:
let rec qsort = function
| [] -> []
| x::xs -> let left,right = List.partition (fun el -> el <= x) xs
qsort left @ [x] @ qsort right
let rec qsortu = function
| [] -> []
| x::xs -> let left = List.filter (fun el -> el < x) xs
let right = List.filter (fun el -> el > x) xs
qsortu left @ [x] @ qsortu right
以交互模式进行测试:
> qsortu [42;42;42;42;42];;
val it : int list = [42]
> qsortu [5;4;4;3;3;3;2;2;2;2;1];;
val it : int list = [1; 2; 3; 4; 5]
> qsortu [3;1;4;1;5;9;2;6;5;3;5;8;9];;
val it : int list = [1; 2; 3; 4; 5; 6; 8; 9]
答案 5 :(得分:0)
由于这是一个面试问题,面试官通常会要求他们对这个问题进行精确处理。
由于不允许使用替代存储(即允许使用O(1)存储,因此您可能会使用某些计数器/指针),显然预计会发生破坏性操作,因此可能值得向面试官指出
现在真正的问题是:你想保留元素的相对顺序吗?即这个操作应该稳定吗?
稳定性极大地影响了可用的算法(从而影响了复杂性)。
最明显的选择是列出Sorting Algorithms,毕竟,一旦数据被排序,就很容易获得独特的元素。
但是如果你想要稳定性,你实际上不能对数据进行排序(因为你无法得到“正确”的顺序),因此我想知道如果涉及稳定性,它是否可以在小于O(N ** 2)的情况下解决。
答案 6 :(得分:0)
本身不使用哈希表,但我知道幕后它是一个哈希表的实现。不过,我想可以发帖,以防它可以提供帮助。这是在JavaScript中,并使用关联数组来记录重复项以传递
function removeDuplicates(arr) {
var results = [], dups = [];
for (var i = 0; i < arr.length; i++) {
// check if not a duplicate
if (dups[arr[i]] === undefined) {
// save for next check to indicate duplicate
dups[arr[i]] = 1;
// is unique. append to output array
results.push(arr[i]);
}
}
return results;
}