Algorithm 在列表中查找单个数字

Algorithm 在列表中查找单个数字,algorithm,puzzle,Algorithm,Puzzle,如果一个列表中所有其他数字正好出现两次,那么找到一个只出现一次的数字的最佳算法是什么 因此,在整数列表中,让我们把它作为一个数组,每个整数重复两次,除了一个。要找到最佳算法,什么是最佳算法。您需要指定最佳算法的含义-对某些人来说,速度是最重要的,并且可以将答案限定为最佳-对于其他人来说,如果解决方案更具可读性,他们可能会原谅几百毫秒 最好是主观的,除非你更具体 也就是说: 遍历数字,对于每个数字,在列表中搜索该数字,当您到达的数字只返回搜索结果数的1时,您就完成了。准时,内存充足 HT=哈希表

如果一个列表中所有其他数字正好出现两次,那么找到一个只出现一次的数字的最佳算法是什么


因此,在整数列表中,让我们把它作为一个数组,每个整数重复两次,除了一个。要找到最佳算法,什么是最佳算法。

您需要指定最佳算法的含义-对某些人来说,速度是最重要的,并且可以将答案限定为最佳-对于其他人来说,如果解决方案更具可读性,他们可能会原谅几百毫秒

最好是主观的,除非你更具体

也就是说:

遍历数字,对于每个数字,在列表中搜索该数字,当您到达的数字只返回搜索结果数的1时,您就完成了。

准时,内存充足

HT=哈希表

HT.clear 把清单按顺序看一遍 对于您看到的每个项目

if(HT.Contains(item)) -> HT.Remove(item)
else
ht.add(item)
最后,HT中的项目就是您要查找的项目

注意:credit@Jared Updike:此系统将查找项目的所有奇数实例

评论:我看不出人们如何投票支持能给您带来卓越性能的解决方案。在哪个宇宙中更好? 我更震惊的是,你在NLogN解决方案中标记了已接受的答案


不过,我确实同意,如果要求内存为常量,那么NLogN将是目前为止最好的解决方案。

我认为使用排序算法,然后通过排序列表查找数字是一种很好的方法


现在的问题是找到最好的排序算法。有很多排序算法,每种算法都有其优缺点,所以这是一个相当复杂的问题。这似乎是一个很好的信息来源。

似乎你能做的最好的事情是遍历列表,对于每个项目,将其添加到一个可见项目列表中,或者如果它已经存在,则将其从可见项目列表中删除,并且在列表的最后,可见项目列表将包含单个元素。在最坏的情况下,这是关于时间的开启和关于空间的n,如果对列表进行排序会更好

它们是整数这一事实并没有真正考虑进去,因为把它们加起来没有什么特别的。。。有吗

问题:


我不明白为什么选择的答案以任何标准来看都是最好的。ON*lgN>ON,它会更改列表或创建列表的副本,这在空间和时间上都更加昂贵。我遗漏了什么吗?

您可以简单地将集合中的元素放入散列,直到找到冲突为止。在ruby中,这是一个单行程序

def find_dupe(array)
  h={}
  array.detect { |e| h[e]||(h[e]=true; false) }
end
因此,find_dupe[1,2,3,4,5,1]将返回1

这实际上是一个常见的面试问题。它通常是关于一个包含一个重复的连续整数的列表。在这种情况下,面试官通常希望你使用n个整数的高斯和技巧,例如从实际和中减去n*n+1/2。教科书上的答案是这样的

def find_dupe_for_consecutive_integers(array)
  n=array.size-1   # subtract one from array.size because of the dupe
  array.sum - n*(n+1)/2
end

不过,这取决于这些数字的大/小/多样性。基数排序可能适用,这将在很大程度上减少ON log N解决方案的排序时间。

最快的ON和最高效的内存O1方法是使用XOR操作

在C中:

这将打印1,这是唯一出现一次的


这是因为第一次命中某个数字时,它会用自身标记num变量,第二次则或多或少地用自身取消标记num。唯一未标记的是您的非重复项。

顺便说一句,您可以扩展这个想法,在重复项列表中快速找到两个唯一的数字

让我们把唯一的数字称为a和b。首先,按照凯尔的建议,使用所有的XOR。我们得到的是a^b。我们知道a^b!=0,从a开始!=B选择a^b的任意1位,并将其用作掩码-更详细地说:选择x作为2的幂,以便x&a^b为非零

现在将列表拆分为两个子列表-一个子列表包含所有数字y,y&x==0,其余的放在另一个子列表中。通过选择x,我们知道a和b在不同的桶中。我们还知道,每一对副本仍然在同一个桶中。所以我们现在可以对每个bucket单独应用yeoldexor-em-all技巧,并完全了解a和b是什么


Bam.

排序方法和异或方法具有相同的时间复杂度。只有在假定两个字符串的按位异或是一个常数时间操作时,XOR方法才会启用。这相当于说数组中整数的大小由一个常数限定。在这种情况下,您可以使用基数排序对数组进行排序


如果数字没有界,则按位XOR需要时间Ok,其中k是位字符串的长度,XOR方法需要Onk。现在,基数排序将按时间对数组进行排序。

Kyle的解决方案显然无法捕获数据集不遵循规则的情况。如果所有数字都是 成对地,算法将给出一个零的结果,这个值与零是唯一一个单次出现的值完全相同

如果有多个单次出现值或三次出现值,则结果也将是不均匀的

测试数据集可能最终会得到一个更昂贵的算法,无论是在内存中还是在时间上

Csmba的解决方案确实显示了一些错误数据,没有或超过一个单一出现值,但没有其他四组。关于他的解决方案,取决于HT的实现,内存和/或时间更重要


如果我们不能确定输入集的正确性,排序和计数或使用哈希表计数都是可行的,而整数本身就是哈希键。

Ruby中的实现:

a = [1,2,3,4,123,1,2,.........]
t = a.length-1
for i in 0..t
   s = a.index(a[i])+1
   b = a[s..t]
   w = b.include?a[i]
   if w == false
       puts a[i]
   end
end

我现在看不到一个被接受的答案,我想知道这是怎么被拒绝的。顺便说一句,我会根据当时可用的答案标记一个可接受的答案。另外,接受并不意味着最好:你的也不是很好:它使用内存。看第一行,粗体:我明确地说它是准时的,在内存上,所以你不会因为我没有指出的任何事情而批评我的建议。我想你必须将哈希表实现扩展为算法,因为问题发起者要求的是算法,而不是适合的最佳数据结构。这是最好的解决方案,只要您能够实际对项目进行异或运算。也就是说,它取决于数据类型。我不确定你是否可以这样做,如果项目是字符串。当然,在这种情况下,它可以通过一层抽象来解决……有几种方法可以通过对单个字符进行异或来对字符串进行异或运算——您只需要有一个与最大字符串一样大的临时变量。如果试图对链表或其他复杂的数据结构进行异或运算是行不通的,但这个问题只与整数有关。这是一个聪明的解决方案,但我认为负数可能会把事情搞砸。你可能会在一个掩码中进行异或运算,这会完全忽略其余的掩码结果。负数和正数一样是一个位域。XOR没有care@NickJohnson:您需要的不是散列是加密安全的,而是它是完美的、双向的或唯一的。您需要能够可靠地从散列返回到对象。@malach Kyle的建议正好解决了问题陈述中所说的问题。如果Onlogn解决方案存在,并且问题陈述没有提到数据错误的可能性,那么编写Onlogn解决方案来保护无效数据是没有意义的。无论如何,这里有一篇文章从信息论的角度用多一点的话解释了这个解决方案:爱这个。如果每个alg问题都有这样的扩展,If将非常有用。
a = [1,2,3,4,123,1,2,.........]
t = a.length-1
for i in 0..t
   s = a.index(a[i])+1
   b = a[s..t]
   w = b.include?a[i]
   if w == false
       puts a[i]
   end
end