[英]Find Elements occurring odd number of times in a list
Let's say we need to find all the elements occurring an odd number of times in a sorted list in O(N) time and O(1) space complexity.假设我们需要在 O(N) 时间和 O(1) 空间复杂度的有序列表中找到所有出现奇数次的元素。
ls = [1,2,2,3,3,3,4,5,5,6,6,6,6,6]
output = [1,3,4,6]
We are not going to return a new list, perhaps will be overwrite the existing one我们不会返回新列表,可能会覆盖现有列表
I have an approach which uses a hashing technique, but it results in O(N) space complexity.我有一种使用散列技术的方法,但它会导致 O(N) 空间复杂度。
I have tried bitwise manipulation using XOR, but I am not able to solve the question.我已经尝试使用 XOR 进行按位操作,但我无法解决这个问题。
Iterate through the list, counting cases where the present item is the same as the previous one, and overwriting towards the start of the list when it is different and the count is an odd number.遍历列表,计算当前项目与前一个项目相同的情况,并在不同且计数为奇数时覆盖列表的开头。
This solution overwrites the existing list rather than allocating a new one, and has O(N) time complexity.此解决方案覆盖现有列表而不是分配新列表,并且具有 O(N) 时间复杂度。 Because the new list will be shorter, we have to
pop
the remaining items from the end of it.因为新列表会更短,所以我们必须从它的末尾
pop
剩余的项目。 (We would normally splice using ls = ls[position:]
but that would assign a new list, which isn't allowed.) (我们通常会使用
ls = ls[position:]
进行拼接,但这会分配一个新列表,这是不允许的。)
def keep_odd_elements(ls):
count = 0
write_position = 0
previous = object()
for item in ls:
if item == previous:
count += 1
else:
# Write the odd-counted numbers towards the start of the list
if count % 2:
ls[write_position] = previous
write_position += 1
count = 1
previous = item
if count % 2:
ls[write_position] = previous
write_position += 1
# Remove the leftover items at the end of the list
for i in range(write_position, len(ls)):
ls.pop()
ls = [1,2,2,3,3,3,4,5,5,6,6,6,6,6]
keep_odd_elements(ls)
print(ls) # [1, 3, 4, 6]
If we remove the requirement not to allocate a new list, then we can write this much more elegantly:如果我们删除不分配新列表的要求,那么我们可以更优雅地编写:
def get_odd_elements(ls):
count = 0
for previous, item in zip([object()] + ls, ls + [object()]):
if item == previous:
count += 1
else:
if count % 2:
yield previous
count = 1
print(list(get_odd_elements([1,2,2,3,3,3,4,5,5,6,6,6,6,6])))
This is C++ code that runs in O(n) and use O(1) auxiliary memory.这是在 O(n) 中运行并使用 O(1) 辅助 memory 的 C++ 代码。
The idea behind this code is very simple, we start from left and counting number of occurrence of a number x
until we arrive to a number y
that not equal x
, because of our input is sorted it guarantee that x
never appear after y
.这段代码背后的想法很简单,我们从左边开始计算数字
x
的出现次数,直到我们到达不等于x
的数字y
,因为我们的输入是排序的,它保证x
永远不会出现在y
之后。 So it's sufficient to check if number of occurrence of x
be odd.因此,检查
x
的出现次数是否为奇数就足够了。
Note that, if the array is not sorted it's provable that, you can't do better than O(nlogn)请注意,如果数组未排序,则可以证明,你不能做得比 O(nlogn)
//Find odd numbers in given sorted list
#include <stdio.h>
int main(){
int ArrayLength;
scanf("%d",&ArrayLength);
int array[ArrayLength];
//Read input sorted array
for ( int i = 0; i < ArrayLength; i++)
scanf("%d",&array[i]);
// Find numbers with odd occurrence
int PreviousLocalOdd=array[0];
int LocalOdd=1;
for ( int i = 1; i < ArrayLength; i++)
{
if (array[i]==PreviousLocalOdd)
LocalOdd++;
if(array[i]!= PreviousLocalOdd)
{
if(LocalOdd % 2==1)
printf("%d",array[i-1]);
LocalOdd=1;
PreviousLocalOdd=array[i];
}
}
if(LocalOdd % 2==1)
printf("%d ",array[ArrayLength-1]);
return 0;
}
To return an array without creating a new one in the function we can use two ways:要返回一个数组而不在 function 中创建一个新数组,我们可以使用两种方法:
Cons: Manipulating the given array is not always recommended as the function could be used in other places like a result comparing function, in which case this would fail.缺点:并不总是建议操作给定的数组,因为 function 可以在其他地方使用,例如比较 function 的结果,在这种情况下会失败。
for(int i=0; i<arr.size(); i++){
currElement = mod(arr[i]);
arr[currElement] = arr[currElement]*-1;
}
for(int i=0; i<arr.size(); i++){
if(arr[i]<0){
ans.push_back(mod(arr[i]));
}
}
prev = -1;
count= 0;
for(int i=0; i<arr.size(); i++){
if(arr[i]==prev){
count++;
}else{
if(count%2!=0)
ans.push_back(prev);
count=1;
prev=arr[i];
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.