I am trying to solve this problem but it doesn't give me the correct answer. Here is the problem:
You are given an array (which will have a length of at least 3, but could be very large) containing integers. The array is either entirely comprised of odd integers or entirely comprised of even integers except for a single integer N. Write a method that takes the array as an argument and returns this "outlier" N.
Here is my code:
a = [2, 4, 6, 8, 10, 3]
b = [2, 4, 0, 100, 4, 11, 2602, 36]
c = [160, 3, 1719, 19, 11, 13, -21]
def find_outlier(list_integers):
for num in list_integers:
if num % 2 != 0:
odd = num
elif num % 2 == 0:
even = num
for num in list_integers:
if len([odd]) < len([even]):
return odd
else:
return even
print(find_outlier(a))
print(find_outlier(b))
print(find_outlier(c))
It spits out 10, 36, 160 and obviously only the last one is correct. Can anyone help me out with it? Thanks!
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
You can nicely use list comprehensions for this:
a = [2, 4, 6, 8, 10, 3]
b = [2, 4, 0, 100, 4, 11, 2602, 36]
c = [160, 3, 1719, 19, 11, 13, -21]
def outlier(lst):
odds = [ el % 2 for el in lst ] # list with 1's when odd, 0's when even
print(odds) # just to show what odds contains
if odds.count(0) == 1: # if the amount of zeros (even numbers) = 1 in this list
print(lst[odds.index(0)]) # find the index of the 'zero' and use it to read the value from the input lst
else:
print(lst[odds.index(1)]) # find the index of the 'one' and use it to read the value from the input lst
outlier(a)
outlier(b)
outlier(c)
Output
[0, 0, 0, 0, 0, 1] # only 1 'one' so use the position of that 'one'
3
[0, 0, 0, 0, 0, 1, 0, 0] # only 1 'one' so use the position of that 'one'
11
[0, 1, 1, 1, 1, 1, 1] # only 1 'zero' so use the position of that 'zero'
160
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With