在数组中查找奇数

时间:2018-02-08 00:40:03

标签: python python-3.x algorithm

我正在尝试解决一个问题,我给出了一个数组,例如[0,0,1,1,2,2,6,9,9,10],其中所有数字都是重复的两次,不包括一个数字,我需要返回不重复的数字。

我想这样做:

def findNumber(self, nums):

    if (len(nums) == 1):
        return nums[0]

    nums_copy = nums[:]

    for i in nums:
        nums_copy.remove(i)

        if i not in nums:
            return i
        else:
            nums_copy.remove(i)

但是当它到达else语句时,会出现以下错误:

  

ValueError:list.remove(x):x不在列表中

i位于nums_copy时会发生这种情况,所以我不明白为什么在这种情况下会出现此错误?

10 个答案:

答案 0 :(得分:10)

比初始方法更容易(也更有效)的方法是使用Counter对象:

 from collections import Counter

 singlet = Counter(nums).most_common()[-1][0]

Counter对象将创建一个类似字典的对象,其中的键是列表中的值,值是它们出现的次数。 most_common方法将返回按降序排序的(value, count)元组列表。

如果您不知道会有多少单身,您可以通过以下方式获取它们的列表:

[k for k, v in Counter(nums).items() if v == 1]

<强>复杂度:

我说我的顶级解决方案效率更高,因为您的原始实现会遍历您的列表,并且每个项目都会调用removein,这将使您获得类似O(n 2 )复杂性。在Counter实现中,Counter对象的构造只进行一次遍历整个列表。 调用most_common时可能会出现这种情况,所以我猜测复杂性是关于O(n log n)。 @Stefan Pochman对此纠正了我:Python使用了Timsort算法在这种情况下非常有效(如果除了其中一个数字出现两次之外,列表实际上几乎已经完全排序了),那么它的复杂性约为O(n)。

答案 1 :(得分:7)

您已nums_copy.remove(i),因此无法再次nums_copy.remove(i)

你可以这样做:

a = [0, 0, 1, 1, 2, 2, 6, 6, 9, 10, 10]

def get_single_instance(array):
  d = {}

  for item in a:
    if item not in d:
      d[item] = 1
    else:
      d[item] += 1

  print d

  for k, v in d.iteritems():
    if v == 1:
      return k

print get_single_instance(a)

结果:9

答案 2 :(得分:4)

最好的算法是使用XOR来查找奇数。

def find_number(nums):
    s = 0 
    for n in nums:
        s ^= n 
    return s 


a = [0, 0, 1, 1, 2, 2, 6, 6, 9, 10, 10] 
print(find_number(a))

答案 3 :(得分:2)

尝试此列表理解。它遍历每个元素并检查它是否重复,如果不重复,则让它保留在新列表中。然后它获取新列表的第0个元素:

a=[0, 0, 1, 1, 2, 2, 6, 6, 9, 10, 10]
[e for e in a if a.count(e)==1][0]

答案 4 :(得分:2)

如果数组已排序,我们可以在O(log n)时间和O(1)额外空格中找到答案。考虑重复的数字对从奇数或偶数索引开始,具体取决于单个元素的位置:

              0  1  2  3  4  5  6  7  8  9   10
             [0, 0, 1, 1, 2, 2, 6, 6, 9, 10, 10]
even indexes: x     x     x     x
odd indexes:                             x

search:                      ^  (0 + 11) / 2 = 5
                         [2, 2] pair starting on even index
                                so the singleton must be ahead

                                      ^  (6 + 11) / 2 = 8
                                     [9] singleton found in two steps!

答案 5 :(得分:1)

这是一种很长的做事方法。根据建议您可以使用nums_copy.remove(i),或者您可以使用count()实现这种方式更为简单:

def findNumber(self, nums):

    for i in nums:

        val = nums.count(i)

        if val == 1:
            return i

这将返回单个号码。只要您没有多个值,此方法就可以了,如果是这样,它将只返回最后一个值。否则,您可以返回一个列表,该列表将存储多个值,如下所示:

def findNumber(self, nums):
    values = []
    for i in nums:

        val = nums.count(i)

        if val == 1:
            values.append(i)

    return values

答案 6 :(得分:1)

假设一个已排序的可迭代(否则对其进行排序),这是第一次出现非重复对:

import more_itertools as mit


iterable = [0, 0, 1, 1, 2, 2, 6, 6, 9, 10, 10] 
next(x for x, y in mit.windowed(iterable, n=2, step=2) if x != y)
# 9

创建非重叠对的另一种方法:

next(x for x, y in mit.sliced(iterable, 2) if x != y)
# 9

more_itertools是第三方库> pip install more_itertools

答案 7 :(得分:1)

在Python中执行此操作的一种好方法是使用collections.Counter来解决O(n)的复杂性:

from collections import Counter

def solution(A):
    for x, occ in Counter(A).items():
        if occ % 2:
            return x

这还将泛化为返回数组中出现奇数次的任何数字。

答案 8 :(得分:0)

对于使用NumPy的任何人来说,这应该与其他答案在速度上具有竞争力:

>>> def get_single_instance_np(arr: np.ndarray):
...     return np.asscalar(arr[np.bincount(arr) == 1])

>>> print(get_single_instance(a))
9

这只返回计数等于1的元素。

答案 9 :(得分:0)

Python 3.6以上


解决方案1 ​​

{'host': 'host1',
 'user': 'firsts_user',
 'time': '01/01'}

解决方案2:

def solution(A):
    # write your code in Python 3.6
    result =0
    for i in A:
        result ^= i
    return result

时间复杂度: from itertools import groupby def solution(A): # write your code in Python 3.6 for key, group_list in groupby(sorted(A)): if len(list(group_list)) % 2 == 1: return key