You could analyze the first three and find the outlier if it is there.
If it is there, you are done. If not, you know the expected parity and can test each subsequent element accordingly.
Creating lists for odd/even numbers, while in principle leading to a result, is unnecessarily memory inefficient.
In code this could look something like:
def find_outlier(seq):
par0 = seq[0] % 2
par1 = seq[1] % 2
if par0 != par1:
return seq[1] if seq[2] % 2 == par0 else seq[0]
# the checks on the first 2 elements are redundant, but avoids copying
# for x in seq[2:]: would do less iteration but will copy the input
for x in seq:
if x % 2 != par0:
return x
a = [2, 4, 6, 8, 10, 3]
b = [2, 4, 0, 100, 4, 11, 2602, 36]
c = [160, 3, 1719, 19, 11, 13, -21]
print(find_outlier(a))
# 3
print(find_outlier(b))
# 11
print(find_outlier(c))
# 160
Your code could not work in its current form:
for num in list_integers:
if num % 2 != 0:
odd = num
elif num % 2 == 0:
even = num
will just have the last seen odd in odd
and the last seen even
in even, without any info on how many were seen. You would need to count how many even/odd numbers are there and eventually need to store the first value encountered for each parity.
for num in list_integers:
if len([odd]) < len([even]):
return odd
else:
return even
is always checking the length of the length-1 lists, and will always return even
.
I see no simple way of fixing your code to make it with comparable efficiency as the above solution. But you could adapt your code to make it reasonably efficient (O(n)
in time -- but without short-circuiting, O(1)
in memory):
def find_outlier_2(seq):
odd = None
even = None
n_odd = n_even = 0
for x in seq:
if x % 2 == 0:
if even is None: # save first occurrence
even = x
n_even += 1
else: # no need to compute the modulus again
if odd is None: # save first occurrente
odd = x
n_odd += 1
if n_even > 1:
return odd
else:
return even
The above is significantly more efficient than some of the other answers in that it does not create unnecessary lists.
For example, these solutions are unnecessarily more memory consuming (being O(n)
in time and O(n)
in memory):
def find_outlier_3(list_integers):
odd = []
even = []
for num in list_integers:
if num % 2 != 0:
odd.append(num)
elif num % 2 == 0:
even.append(num)
if len(odd) < len(even):
return odd[0]
else:
return even[0]
def find_outlier_4(lst):
odds = [el % 2 for el in lst]
if odds.count(0) == 1:
return lst[odds.index(0)]
else:
return lst[odds.index(1)]
Simple benchmarks show that these solutions are also slower:
%timeit [find_outlier(x) for x in (a, b, c) * 100]
# 10000 loops, best of 3: 128 µs per loop
%timeit [find_outlier_2(x) for x in (a, b, c) * 100]
# 1000 loops, best of 3: 229 µs per loop
%timeit [find_outlier_3(x) for x in (a, b, c) * 100]
# 1000 loops, best of 3: 341 µs per loop
%timeit [find_outlier_4(x) for x in (a, b, c) * 100]
# 1000 loops, best of 3: 248 µs per loop