#python #algorithm
#python #алгоритм
Вопрос:
Пусть A — непустое множество целых чисел. Напишите функцию find, которая выводит непустое подмножество A с максимальным произведением. Например, найти([-1, -2, -3, 0, 2]) = 12 = (-2)*(-3)*2
Вот что я думаю: разделите список на список положительных целых чисел и список отрицательных целых чисел:
- Если у нас есть четное число отрицательных целых чисел, умножьте все в обоих списках, и мы получим ответ.
- Если у нас нечетное число отрицательных целых чисел, найдите наибольшее и удалите его из списка. Затем умножьте все в обоих списках.
- Если список содержит только один элемент, верните этот элемент.
Вот мой код на Python:
def find(xs):
neg_int = []
pos_int = []
if len(xs) == 1:
return str(xs[0])
for i in xs:
if i < 0:
neg_int.append(i)
elif i > 0:
pos_int.append(i)
if len(neg_int) == 1 and len(pos_int) == 0 and 0 in xs:
return str(0)
if len(neg_int) == len(pos_int) == 0:
return str(0)
max = 1
if len(pos_int) > 0:
for x in pos_int:
max=x*max
if len(neg_int) % 2 == 1:
max_neg = neg_int[0]
for j in neg_int:
if j > max_neg:
max_neg = j
neg_int.remove(max_neg)
for k in neg_int:
max = k*max
return str(max)
Я что-то пропустил? P.S. Это проблема из Google foobar challenge, я, по-видимому, пропустил один случай, но я не знаю, какой именно.
Комментарии:
1. Я имел в виду численно наибольшее отрицательное значение, как -1> -3
2. Сделайте max_neg = abs(neg_int[0]) .. и выполняйте сравнения на основе абсолютного значения
3. Должен ли набор иметь минимальный размер? например
[2, 3, 1, 1]
, приводит к тому же продукту,[2, 3]
что и . Говорит ли задача что-нибудь о том, как вы должны устранить это несоответствие?4. Нет, это не так. Я должен сказать, что технически это не набор, поскольку могут существовать повторяющиеся значения.
5. @Lewis: думаю, я нашел ошибку в вашем коде: скажем, ввод:
[-1]
, ваш код возвращается0
в качестве ответа.. Также в некоторых крайних случаях выreturn 0
вместоreturn str(0)
Ответ №1:
from functools import reduce
from operator import mul
def find(array):
negative = []
positive = []
zero = None
removed = None
def string_product(iterable):
return str(reduce(mul, iterable, 1))
for number in array:
if number < 0:
negative.append(number)
elif number > 0:
positive.append(number)
else:
zero = str(number)
if negative:
if len(negative) % 2 == 0:
return string_product(negative positive)
removed = max(negative)
negative.remove(removed)
if negative:
return string_product(negative positive)
if positive:
return string_product(positive)
return zero or str(removed)
Ответ №2:
Вы можете упростить эту проблему с reduce
помощью (in functools
в Py3)
import functools as ft
from operator import mul
def find(ns):
if len(ns) == 1 or len(ns) == 2 and 0 in ns:
return str(max(ns))
pos = filter(lambda x: x > 0, ns)
negs = sorted(filter(lambda x: x < 0, ns))
return str(ft.reduce(mul, negs[:-1 if len(negs)%2 else None], 1) * ft.reduce(mul, pos, 1))
>>> find([-1, -2, -3, 0, 2])
'12'
>>> find([-3, 0])
'0'
>>> find([-1])
'-1'
>>> find([])
'1'
Комментарии:
1. Это решение, похоже, взрывается при вводе [-1] и не возвращает строки.
2. Хорошо, это не охватывало все особые случаи. Добавлена одна защита.
Ответ №3:
Вот решение в одном цикле:
def max_product(A):
"""Calculate maximal product of elements of A"""
product = 1
greatest_negative = float("-inf") # greatest negative multiplicand so far
for x in A:
product = max(product, product*x, key=abs)
if x <= -1:
greatest_negative = max(x, greatest_negative)
return max(product, product // greatest_negative)
assert max_product([2,3]) == 6
assert max_product([-2,-3]) == 6
assert max_product([-1, -2, -3, 0, 2]) == 12
assert max_product([]) == 1
assert max_product([-5]) == 1
Дополнительный кредит: что, если бы ограничение целого числа было ослаблено? Какую дополнительную информацию вам нужно собрать во время цикла?
Ответ №4:
Вот еще одно решение, которое не требует библиотек :
def find(l):
if len(l) <= 2 and 0 in l: # This is the missing case, try [-3,0], it should return 0
return max(l)
l = [e for e in l if e != 0] # remove 0s
r = 1
for e in l: # multiply all
r *= e
if r < 0: # if the result is negative, remove biggest negative number and retry
l.remove(max([e for e in l if e < 0]))
r = find(l)
return r
print(find([-1, -2, -3, 0, 2])) # 12
print(find([-3, 0])) # 0
Редактировать :
Я думаю, что я нашел недостающий случай, когда в списке всего два элемента, а самый высокий равен 0.
Комментарии:
1. Это очень хорошее решение. Но он не проходит тот же тестовый пример, что и мой код. (К сожалению, я понятия не имею, в каком случае это так)
2. @Lewis моя мысль тоже, но на самом деле я не вижу, в каком случае это ни то, ни другое. Я буду продолжать искать, эта проблема забавная 🙂
3. На самом деле ваше решение терпит неудачу и в другом случае: find([0,-1)] выводит 1 вместо 0.
4. Я только что обновил вопрос. Пожалуйста, смотрите картинку в описании. 🙂
5. Когда вы даете этому коду одно отрицательное число,
find([-3])
он возвращает1
.