21

How do I find the missing number from a sorted list the pythonic way?

a=[1,2,3,4,5,7,8,9,10]

I have come across this post but is there a more and efficient way to do this?

codeforester
  • 39,467
  • 16
  • 112
  • 140
Rajeev
  • 44,985
  • 76
  • 186
  • 285
  • 1
    There is a generalization of this problem! Refer the problem: http://stackoverflow.com/questions/3492302/easy-interview-question-got-harder-given-numbers-1-100-find-the-missing-numbe – Sreejith Menon Jan 08 '17 at 02:29

18 Answers18

25
>>> a=[1,2,3,4,5,7,8,9,10]
>>> sum(xrange(a[0],a[-1]+1)) - sum(a)
6

alternatively (using the sum of AP series formula)

>>> a[-1]*(a[-1] + a[0]) / 2 - sum(a)
6

For generic cases when multiple numbers may be missing, you can formulate an O(n) approach.

>>> a=[1,2,3,4,7,8,10]
>>> from itertools import imap, chain
>>> from operator import sub
>>> print list(chain.from_iterable((a[i] + d for d in xrange(1, diff))
                        for i, diff in enumerate(imap(sub, a[1:], a))
                        if diff > 1))
[5, 6, 9]
Abhijit
  • 62,056
  • 18
  • 131
  • 204
15

This should work:

a = [1, 3, 4, 5, 7, 8, 9, 10]
b = [x for x in range(a[0], a[-1] + 1)]
a = set(a)
print(list(a ^ set(b)))
>>> [2, 6]
Camilo Martinez M.
  • 1,420
  • 1
  • 7
  • 21
Samman Thapa
  • 159
  • 1
  • 3
  • 1
    Elegant solution, which doesn't involve extra modules (which is the case with the solution provided by @Abhijit). The only issue (not sure if it exists!) is the conversion to a set. If the list already contains unique numbers, I'm not sure what the performance impact would be when the `set()` conversion is applied. Sadly the `^` operator only works on sets hence the conversion needs to take place even when one knows that the list is actually a set (though stored as a list). – rbaleksandar Mar 10 '20 at 10:11
  • @rbaleksandar I believe the set allows one to perform the symmetric difference between the two "lists". – JMortey Mar 24 '21 at 18:08
  • Hi, sorry for jumping into your answer this late. Wondering if you could enlighten me why for the range, the last element need to be added with a value of 1? I tried without it and I am still able to get the same answer.. – dissidia May 28 '22 at 18:35
  • @dissidia `range(0,10)` would only cover the values from 0 to 9, inclusive. To also cover 10, 1 is added to the last value of `a`. Of course, it doesn't really matter because if 10 were missing from `a`, how would we know about that? – Raketenolli Jun 15 '22 at 14:47
8
1 + 2 + 3 + ... + (n - 1) + n = (n) * (n + 1)/2

so the missing number is:

(a[-1] * (a[-1] + 1))/2 - sum(a)
Steve P.
  • 14,489
  • 8
  • 42
  • 72
Gabriel
  • 3,564
  • 1
  • 27
  • 49
  • Your answer is correct, but given your first sentence, it would make a lot more sense if you actually used that fact in the answer, ie remove the first part and replace it with the product... – Steve P. Dec 21 '13 at 11:58
  • Modified it to be relevant to the problem at hand. – Steve P. Dec 21 '13 at 12:08
7
set(range(a[len(a)-1])[1:]) - set(a)

Take the set of all numbers minus the set of given.

Saša Šijak
  • 8,717
  • 5
  • 47
  • 82
7

And another itertools way:

from itertools import count, izip

a=[1,2,3,4,5,7,8,9,10]
nums = (b for a, b in izip(a, count(a[0])) if a != b)
next(nums, None)
# 6
Jon Clements
  • 138,671
  • 33
  • 247
  • 280
2

This will handle the cases when the first or last number is missing.

>>> a=[1,2,3,4,5,7,8,9,10]
>>> n = len(a) + 1
>>> (n*(n+1)/2) - sum(a)
6
JMortey
  • 55
  • 7
1

If many missing numbers in list:

>>> a=[1,2,3,4,5,7,8,10]
>>> [(e1+1) for e1,e2 in zip(a, a[1:]) if e2-e1 != 1]
[6, 9]
ndpu
  • 22,225
  • 6
  • 54
  • 69
1
def find(arr):
        for x in range(0,len(arr) -1):
                if arr[x+1] - arr[x] != 1:
                        print arr[x] + 1
josliber
  • 43,891
  • 12
  • 98
  • 133
Prat_yow
  • 23
  • 1
  • 8
1

Simple solution for the above problem, it also finds multiple missing elements.

a = [1,2,3,4,5,8,9,10]
missing_element = []
for i in range(a[0], a[-1]+1):
    if i not in a:
        missing_element.append(i)

print missing_element

o/p: [6,7]

Venkatesh_CTA
  • 120
  • 10
1

Here is the simple logic for finding mising numbers in list.

l=[-10,-5,2,4,5,9,20]
s=l[0]
e=l[-1]
x=sorted(range(s,e+1))
l_1=[]
for i in x:
    if i not in l:
        l_1.append(i)
print(l_1)
1
def findAllMissingNumbers(a):
   b = sorted(a)
   return list(set(range(b[0], b[-1])) - set(b))
David Buck
  • 3,752
  • 35
  • 31
  • 35
Shyambeer Singh
  • 318
  • 2
  • 9
1
L=[-5,1,2,3,4,5,7,8,9,10,13,55]

missing=[]

for i in range(L[0],L[-1]):
    if i not in L:
        missing.append(i)
print(missing)
Joe121
  • 62
  • 5
  • Hi Joe, with 17 other answers already present, it would be great if you could add an explanation to your code to help us understand how it is different from other answers and how it solves the problem in the way that other answers dont. Thanks! – Simas Joneliunas Feb 18 '22 at 01:36
0

A simple list comprehension approach that will work with multiple (non-consecutive) missing numbers.

def find_missing(lst):
    """Create list of integers missing from lst."""
    return [lst[x] + 1 for x in range(len(lst) - 1) 
            if lst[x] + 1 != lst[x + 1]]
jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
0

There is a perfectly working solution by @Abhiji. I would like to extent his answer by the option to define a granularity value. This might be necessary if the list should be checked for a missing value > 1:

from itertools import imap, chain
from operator import sub

granularity = 3600
data = [3600, 10800, 14400]

print list(
  chain.from_iterable(
    (data[i] + d for d in xrange(1, diff) if d % granularity == 0) 
      for i, diff in enumerate(imap(sub, data[1:], data)) 
        if diff > granularity
  )
)

The code above would produce the following output: [7200].

As this code snipped uses a lot of nested functions, I'd further like to provide a quick back reference, that helped me to understand the code:

Kevin Katzke
  • 3,581
  • 3
  • 38
  • 47
0

Less efficient for very large lists, but here's my version for the Sum formula:

def missing_number_sum(arr):
    return int((arr[-1]+1) * arr[-1]/2) - sum(arr)
dbc
  • 104,963
  • 20
  • 228
  • 340
0

If the range is known and the list is given, the below approach will work.

a=[1,2,3,4,5,7,8,9,10]
missingValues = [i for i in range(1, 10+1) if i not in a]
print(missingValues)

# o/p: [6] 
laplace
  • 656
  • 7
  • 15
-1
set(range(1,a[-1])) | set(a)

Compute the union of two sets.

M4rtini
  • 13,186
  • 4
  • 35
  • 42
-1

I used index position. this way i compare index and value.

a=[0,1,2,3,4,5,7,8,9,10]

for i in a:
  print i==a.index(i)
kuro
  • 3,214
  • 3
  • 15
  • 31
Andre
  • 1
  • 2