(Quick note: please do not use list
as a variable name, as it's also the name of a type. I'm going to use list_
instead)
Depending on the interpretation, it could be that they want you to iterate over the list just once.
The statement "v in list" potentially iterates over the full list, which means it's yet another pass.
If you know nothing about the list, except that they are numbers, one approach would be to store the values seen so far in a set, which has a more efficient "in".
def is_sum_of_2nums_in_list_k(list_, k):
seen = set()
for i in list_:
if k - i in seen:
return True
seen.add(i)
return False
This works the same as your initial solution, but for each new number, it only checks if the sum of that number and an earlier number add up k
.
As a downside: storage needs to be allocated for the set seen
, so this does not work with constant memory.
If on the other hand, we have also been told that the list was ordered, we can go for a different approach
def is_sum_of_2nums_in_list_k(list_, k):
# Assumption: `list_` is ordered.
left, right = 0, len(list_) - 1
while left < right:
total = list_[left] + list_[right]
if total == k:
return True
if total < k:
left += 1
if total > k:
right -= 1
return False
This is a bit more complicated, but requires constant extra storage.
in
is O(len) for lists afaik. In the worst case, both thefor
andin
will do a full pass. Iflist
was a set, this would be much more efficient. \$\endgroup\$in
also iterates, meaning I iterate twice in my given solution) \$\endgroup\$