You are going to have to compare if each item of a list is contained in the other one; probably the most efficient iway to do this is to use sets() and extract their difference.

target_list = ["one", "two", "three", "four", "five"]
output_list = ['two','three','four', 'five']

print(set(target_list).difference(set(output_list)))

output:

set(['one'])
Answer from Reblochon Masque on Stack Overflow
๐ŸŒ
TutorialsPoint
tutorialspoint.com โ€บ find-missing-elements-in-list-in-python
Find missing elements in List in Python
listA = [1,5,6, 7,11,14] # Original list print("Given list : ",listA) # using range and max res = [ele for ele in range(max(listA) + 1) if ele not in listA] # Result print("Missing elements from the list : \n" ,res)
๐ŸŒ
GeeksforGeeks
geeksforgeeks.org โ€บ python-find-missing-elements-in-list
Python | Find missing elements in List | GeeksforGeeks
April 6, 2023 - Method #1 : Using list comprehension We can perform the task of finding missing elements using the range function to get the maximum element fill and then insert the elements if there is a miss.
๐ŸŒ
w3resource
w3resource.com โ€บ python-exercises โ€บ list โ€บ python-data-type-list-exercise-42.php
Python: Find missing and additional values in two lists - w3resource
... # Define two lists 'list1' ... values in 'list2' by finding the set difference between 'list1' and 'list2' missing_values = set(list1).difference(list2) # Print the missing values in the second list 'list2' print('Missing ...
Top answer
1 of 6
2

You need to be aware that i < len(A) is causing some problem.

Given this example:

A = [1, 2, 3, 5]

It looks pretty clear that the desired answer is 4, but your function is giving None. It's because len(A) == 4 and thus, your loop condition is i < 4, which effectively enumerates i from 1 to 3.

Since you want to find out the missing number, you might as well stop the loop when i reaches the largest number in the list, rather than the length of the list, so:

while i < max(A):

would be right.

2 of 6
2

Find missing numbers

Using range(start, stop) we can build a sorted list which already contains all the numbers. Now it's just matter of finding the missing values in your list.

Our range will be made using the lower and higher values of your list. range(min(A), max(A)).

def solution(A):
    missings = []
    for n in range(min(A), max(A)): # Iterate over each number in the sorted and complete list.
        if n not in A: # If that number isn't in your list.
            missings.append(n)
    return missings

Or as a list comprehension in one line:

def solution(A): return [n for n in range(min(A), max(A)) if n not in A]

Example:

>>> solution([1, 9, 4, 3, 11, 5, 7])
[2, 6, 8, 10]

Find non-negative missing numbers

But you said "find a missing positive integer", so you don't want negatives ones.

Just change the min(A) part of range(min(A), max(A)) to range(max(0, min(A)), max(A)).
max(0, min(A)) will use max to give you the bigger number between 0 and your lower actual value, so negative ones are replaced by 0.

Example:

>>> solution([-4, -5, 1, 9])
[0, 2, 3, 4, 5, 6, 7, 8]

Find non-negative missing number after the lower non-negative number

But as said before, you only said: "find a missing positive integer", so at first, I understood you don't want negatives ones.
But, what if you only want the missing (as my first idea) non-negative values (as the second idea) after the lower non-negative value (new idea)?

Easy!
Just change the min(A) part of range(min(A), max(A)) to range(min([n for n in A if n >= 0]), max(A)).
min([n for n in A if n >= 0]) will look for the lower non-negative value in your list.

Example:

>>> solution([-4, -5, 3, 9])
[4, 5, 6, 7, 8]
๐ŸŒ
TutorialsPoint
tutorialspoint.com โ€บ article โ€บ python-program-to-find-missing-and-additional-values-in-two-lists
Python program to find missing and additional values in two lists?
def demo(x, y): set1 = set(x) set2 = set(y) a = set1.difference(set2) b = set2.difference(set1) return list(a), list(b) x = [11,2,33,22,44] y = [44,2,11,33,55] a, b = demo(x, y) print("Missing:", a) print("Additional:", b) ... In the following ...
๐ŸŒ
GeeksforGeeks
geeksforgeeks.org โ€บ python-find-missing-additional-values-two-lists
Python โ€“ Find missing and additional values in two lists | GeeksforGeeks
December 17, 2024 - For example, we might have a list of expected items and another list showing what we have in stock. We can easily identify missing and additional items by comparing the two lists. List comprehension is a compact and easy way to find missing and additional values.
Find elsewhere
๐ŸŒ
Django Central
djangocentral.com โ€บ find-missing-number-in-an-array-using-python
Find Missing Number in a given Array Using Python
arr = [1,2,3,4,5,6,7,9,10] missing_elements = [] for ele in range(arr[0], arr[-1]+1): if ele not in arr: missing_elements.append(ele) print(missing_elements) ... arr = [1,2,3,4,5,7,6,9,10] missing_elemnts = [item for item in range(arr[0], arr[-1]+1) if item not in arr] print(missing_elemnts) ...
๐ŸŒ
TutorialsPoint
tutorialspoint.com โ€บ find-missing-numbers-in-a-sorted-list-range-in-python
Find missing numbers in a sorted list range in Python
listA = [1,5,6, 7,11,14] # Original list print("Given list : ",listA) # using range res = [x for x in range(listA[0], listA[-1]+1) if x not in listA] # Result print("Missing elements from the list : \n" ,res) Running the above code gives us the following result โˆ’ ยท Given list : [1, 5, 6, 7, 11, 14] Missing elements from the list : [2, 3, 4, 8, 9, 10, 12, 13]
๐ŸŒ
AskPython
askpython.com โ€บ home โ€บ find missing and repeating elements in python [easy step-by-step]
Find Missing and Repeating Elements in Python [Easy Step-By-Step] - AskPython
August 9, 2021 - Now, the manual approach is to traverse the list one time and check the count of each number. If the count of any number is equal to 2*n then we found the repeating number and then traverse through the elements to check for the occurrence of each number: one, two, three, and so on. If any of those numbers are not present, then return that number as the missing number.
๐ŸŒ
coderz.py
coderzpy.com โ€บ home โ€บ find the missing element in python
Find the Missing Element in Python - coderz.py
September 28, 2020 - The value of the first iterator is the missing element. This solution is also O(NlogN). Here is the solution for this approach: def finder(arr1,arr2): # Sort the arrays arr1.sort() arr2.sort() # Compare elements in the sorted arrays for num1, num2 in zip(arr1,arr2): if num1!= num2: return num1 # Otherwise return last element return arr1[-1]
๐ŸŒ
w3resource
w3resource.com โ€บ python-exercises โ€บ challenges โ€บ 1 โ€บ python-challenges-1-exercise-8.php
Python: Find missing numbers from a list - w3resource
... def missing_numbers(num_list): original_list = [x for x in range(num_list[0], num_list[-1] + 1)] num_list = set(num_list) return (list(num_list ^ set(original_list))) print(missing_numbers([1,2,3,4,6,7,10])) print(missing_numbers([10,11...
Top answer
1 of 16
71

If the input sequence is sorted, you could use sets here. Take the start and end values from the input list:

def missing_elements(L):
    start, end = L[0], L[-1]
    return sorted(set(range(start, end + 1)).difference(L))

This assumes Python 3; for Python 2, use xrange() to avoid building a list first.

The sorted() call is optional; without it a set() is returned of the missing values, with it you get a sorted list.

Demo:

>>> L = [10,11,13,14,15,16,17,18,20]
>>> missing_elements(L)
[12, 19]

Another approach is by detecting gaps between subsequent numbers; using an older itertools library sliding window recipe:

from itertools import islice, chain

def window(seq, n=2):
    "Returns a sliding window (of width n) over data from the iterable"
    "   s -> (s0,s1,...s[n-1]), (s1,s2,...,sn), ...                   "
    it = iter(seq)
    result = tuple(islice(it, n))
    if len(result) == n:
        yield result    
    for elem in it:
        result = result[1:] + (elem,)
        yield result

def missing_elements(L):
    missing = chain.from_iterable(range(x + 1, y) for x, y in window(L) if (y - x) > 1)
    return list(missing)

This is a pure O(n) operation, and if you know the number of missing items, you can make sure it only produces those and then stops:

def missing_elements(L, count):
    missing = chain.from_iterable(range(x + 1, y) for x, y in window(L) if (y - x) > 1)
    return list(islice(missing, 0, count))

This will handle larger gaps too; if you are missing 2 items at 11 and 12, it'll still work:

>>> missing_elements([10, 13, 14, 15], 2)
[11, 12]

and the above sample only had to iterate over [10, 13] to figure this out.

2 of 16
12

Assuming that L is a list of integers with no duplicates, you can infer that the part of the list between start and index is completely consecutive if and only if L[index] == L[start] + (index - start) and similarly with index and end is completely consecutive if and only if L[index] == L[end] - (end - index). This combined with splitting the list into two recursively gives a sublinear solution.

# python 3.3 and up, in older versions, replace "yield from" with yield loop

def missing_elements(L, start, end):
    if end - start <= 1: 
        if L[end] - L[start] > 1:
            yield from range(L[start] + 1, L[end])
        return

    index = start + (end - start) // 2

    # is the lower half consecutive?
    consecutive_low =  L[index] == L[start] + (index - start)
    if not consecutive_low:
        yield from missing_elements(L, start, index)

    # is the upper part consecutive?
    consecutive_high =  L[index] == L[end] - (end - index)
    if not consecutive_high:
        yield from missing_elements(L, index, end)

def main():
    L = [10,11,13,14,15,16,17,18,20]
    print(list(missing_elements(L,0,len(L)-1)))
    L = range(10, 21)
    print(list(missing_elements(L,0,len(L)-1)))

main()
Top answer
1 of 2
4

Your doctest is misformatted; fix that. Also, don't add a space before the docstring and don't give it a useless header like "Doctest": give it real documentation. Beware of PEP-8 spacing, too.

Your parameter int_array is misnamed; you don't take an array but a list. Best call it just integers, which is good for duck-typing.

You default min_val and max_val to False... but False == 0! This means that if the user passes in 0 as min_val or max_val it would be ignored. You should default unknown values to, say, None. I would also rename these to smallest and largest.

You do

integers = sorted(integers)

which is \$\mathcal{O}(n \log n)\$. This is OK, but is a suboptimal running time. I shall leave it for now.

You do mention

I tried not to use min and max because I heard that they are \$\mathcal{O}(n)\$.

but you run these at most twice and

$$ 2 \cdot \mathcal{O}(n) = \mathcal{O}(2n) = \mathcal{O}(n) $$

Since the overall cost is at best (hopefully) \$\mathcal{O}(n + (largest - smallest)) > \mathcal{O}(n)\$, this does not affect overall running times. They are also very fast operations. However, since you're already sorting the array, indexing will be faster.

All of this is not needed if you make your main loop more robust:

#Checking to see if the min & max values currently exist
#If they do not then add them to the resultant array as they are missing numbers
if min_val < first_in_int_array:            
    int_array.insert(0, min_val)
    result.append(min_val)

if max_val > last_in_int_array:
    int_array.insert(len(int_array), max_val)
    result.append(max_val)

#Dealing with case where max_val < last_in_int_array but not in array 
#Example: max_val = 2 int_array = [1,3]
#Also dealing with the analogous case for min_val and first_in_int_array
#Deal with this using exceptions
try:
    min_pos = int_array.index(min_val)

except Exception as e:
    result.append(min_val)
    min_pos = bisect_left(int_array, min_val)
    int_array.insert(min_pos, min_val)



try:
    max_pos = int_array.index(max_val)
except Exception as e:
    result.append(max_val)
    max_pos = bisect_left(int_array, max_val)
    int_array.insert(max_pos, max_val)

You should also fix up the default case to be more robust:

if not integers:
    if smallest is None or largest is None:
        return []

    return list(range(smallest, largest+1))

Maybe even throw an error with smallest or largest undefined for an empty list. Maybe.

Your main loop should probably loop over the whole array, not some subsection.

for integer in integers:

Then one can do just

result.extend(range(smallest+1, integer))

since that is the difference between them. You can then set

smallest = integer

and carry on. You will need to deal with integer < smallest and largest > integers[-1], and also missing smallest. One quick fix is

result = []
for integer in integers:
    if not smallest <= integer <= largest:
        continue

    result += range(smallest, integer)

    if integer >= smallest:
        smallest = integer+1

result += range(smallest, largest+1)
return result

result will already be sorted, so don't call .sort. Use .extend over += as well.

More efficient than sorting \$\left(\mathcal{O}(n \log n)\right)\$ is to use a set. However, to produce output one would have to loop over a range. This can be done with:

seen = set(integers)
return [i for i in range(smallest, largest) if i not in seen]

This condenses the whole function down to just

if smallest is None:
    smallest = min(integers)

if largest is None:
    largest = max(integers)

seen = set(integers)
return [i for i in range(smallest, largest+1) if i not in seen]

This is similar to Caridorc's except

  • I am not using inline if statements,
  • I have made a set before checking if i not in seen; this is \$\mathcal{O}(n)\$ for lists but \$\mathcal{O}(1)\$ for sets.

Consider, document and implement what find_missing([]) should do.

2 of 2
4
  • You say 'Doctest' but then you format them badly with unecessary newlines and you do not actually run the tests.

  • Your code is much more complex than it should be. When writing a programme remember that it should be the simplest possible.

The function down below behaves exactly like yours but:

  1. It is 3 lines of code instead of 50.
  2. The doctest is properly formatted so that you can actually run it.
  3. The doctest is actually run when the script is executed as the main file.

:

import doctest

def find_missing(integers_list,start=None,limit=None):
    """
    Given a list of integers and optionally a start and an end, finds all
    the integers from start to end that are not in the list.

    'start' and 'end' default respectivly to the first and the last item of the list.

    Doctest:

    >>> find_missing([1,2,3,5,6,7], 1, 7)
    [4]

    >>> find_missing([2,3,6,4,8], 2, 8)
    [5, 7]

    >>> find_missing([1,2,3,4], 1, 4)
    []

    >>> find_missing([11,1,1,2,3,2,3,2,3,2,4,5,6,7,8,9],1,11)
    [10]

    >>> find_missing([-1,0,1,3,7,20], -1, 7)
    [2, 4, 5, 6]

    >>> find_missing([-2,0,3], -5, 2)
    [-5, -4, -3, -1, 1, 2]

    >>> find_missing([2],4,5)
    [4, 5]

    >>> find_missing([3,5,6,7,8], -3, 5)
    [-3, -2, -1, 0, 1, 2, 4]

    >>> find_missing([1,2,4])
    [3]

    """
    start = start if start is not None else integers_list[0]
    limit = limit if limit is not None else integers_list[-1]
    return [i for i in range(start,limit + 1) if i not in integers_list]


def _test():
    doctest.testmod()

if __name__ == "__main__":
    _test()