LVV>>Ну так это и есть оптимальный. E>Ну так в теме сравнивают два таких решения
Пардон, вариант второго товарища — лучше.
У него в явном виде однократный цикл, а у тебя есть вложенный двукоратный.
У него простой проход по списку чисел, а у тебя потом еще дополнительные вычисления после прохода.
И памяти у него меньше используется.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Самое простая для школьника реализация поиска 9 наибольших чисел и перебор всех 9 * 9/2 пар выглядит так:
long maxMul(int A[], int N)
{
int indicies[9];
int maximum[9] = {-1,-1,-1,-1,-1,-1,-1,-1,-1};
//find 9 maximums in array and save themfor (int i = 0; i < 9; i++)
{
for (int j = 0; j < N; j++)
if (j != i && maximum[i] < A[j])
{
maximum[i] = A[j];
indicies[i] = j;
}
A[indicies[i]] = -1;
}
long maxMul = -1;
for (int i = 0; i < 9; i++)
for (int j = i + 1; j < 9; j++)
{
if (abs(indicies[i] - indicies[j]) >= 8)
{
long mul = long(maximum[i]) * long(maximum[j]);
maxMul = max(maxMul, mul);
}
}
return maxMul;
}
Здравствуйте, LaptevVV, Вы писали:
LVV>У него в явном виде однократный цикл, а у тебя есть вложенный двукоратный.
Зато мой очевиднее.
А "вложенный" он константный. Это итерация 36 пар — кандидатов. Число пар от N не зависит, начиная с N == 9
LVV>У него простой проход по списку чисел, а у тебя потом еще дополнительные вычисления после прохода. LVV>И памяти у него меньше используется.
На 9 int'ов
Я же про то и написал, что в моём решении уже не понятно, куда лучше. Типа за снижение расхода памяти с 18 int'ов до 8-9 бороться?
Ну, то есть, вот ты пишешь какую-то контрольную/экзамен/собеседование и т. д, придумал такое решение. Что дальше делать, искать решение лучше или переходить к другим задачкам, или говорить, что готов?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, iriska2, Вы писали:
I>Самое простая для школьника реализация поиска 9 наибольших чисел и перебор всех 9 * 9/2 пар выглядит так:
За это решение Вы бы получили 3 бала, а не 4. Это решение имеет потребность в памяти O(N), так как 9 раз проходит по входному массиву, а следовательно этот массив должен существовать в памяти. По времени он линеен от N, т.е. удовлетворяет одному из двух требований. Поэтому 3, а не 2 балла. Остальные решения выше могут работать с неопределенным числом входным данных, поэтому по памяти у них нет зависимости от N. И за них авторы получили бы 4 балла.
Здравствуйте, Serg27, Вы писали:
S>Здравствуйте, iriska2, Вы писали:
I>>Самое простая для школьника реализация поиска 9 наибольших чисел и перебор всех 9 * 9/2 пар выглядит так: S>За это решение Вы бы получили 3 бала, а не 4. Это решение имеет потребность в памяти O(N), так как 9 раз проходит по входному массиву, а следовательно этот массив должен существовать в памяти. По времени он линеен от N, т.е. удовлетворяет одному из двух требований. Поэтому 3, а не 2 балла. Остальные решения выше могут работать с неопределенным числом входным данных, поэтому по памяти у них нет зависимости от N. И за них авторы получили бы 4 балла.
Да, вы правы, я невнимательно прочитал условие, подумал что на входе уже массив, к тому же проверка i != j тоже лишняя.
Здравствуйте, Sergei MO, Вы писали: SM>Контрпример: SM>
SM>2, 5, 2, 2, 2, 2, 2, 2, 2, 1
SM>
SM>Чтобы этот алгоритм сработал, нужно брать не менее 16 наибольших чисел.
Цитата из моего исходного сообщения:
К тому же закралось сомнение в правильности гипотезы, которую я положил в основу решения. Только я решил ее доказывать, как сразу нашел нормальное решение...
Именно о гипотезе о том, что решение надо искать среди 9 наибольших чисел, и шла речь. Ну и контрпример я начал обдумывать примерно такой же. Но после прихода в голову простого решения, желания думать на эту тему пропало... (к тому же это был очень поздний вечер).
В общем надо доказывать, ну и находить размер данных (9, 16, 17 ????)
Здравствуйте, Serg27, Вы писали:
S>Для заданной последовательности неотрицательных целых чисел необходимо найти максимальное произведение двух её элементов, номера которых различаются не менее чем на 8. Значение каждого элемента последовательности не превышает 1000. Количество элементов последовательности не превышает 10000.
S>Б. Напишите программу для решения поставленной задачи, которая будет эффективна как по времени, так и по памяти (или хотя бы по одной из этих характеристик).
S>Программа считается эффективной по времени, если время работы программы пропорционально количеству элементов последовательности N, т.е. при увеличении N в k раз время работы программы должно увеличиваться не более чем в k раз. Программа считается эффективной по памяти, если размер памяти, использованной в программе для хранения данных, не зависит от числа N и не превышает 1 килобайта.
def max_product(numbers, window):
m = numbers[0]
r = 0
for i in xrange(window, len(numbers)):
r = max(r, numbers[i] * m)
m = max(m, numbers[i + 1 - window])
return r
print (max_product([100, 45, 55, 245, 35, 25, 10, 10, 10, 26], 8))
Чужие решения не смотрел, т.к. у самого решалка длинная.
Ищем максимум от произведения текущего элемента (за окном справа) на максимум из просмотренных (за окном слева). Если ответ N это произведение a[i] * a[j] при i + k <= j, мы найдем решение, просматривания элемент с индексом j, потому что a[j] * max(a[0], ..., a[j-k]) >= a[j] * a[i].
Здравствуйте, crawling-web-crawler, Вы писали: CWC>Ищем максимум от произведения текущего элемента (за окном справа) на максимум из просмотренных (за окном слева). Если ответ N это произведение a[i] * a[j] при i + k <= j, мы найдем решение, просматривания элемент с индексом j, потому что a[j] * max(a[0], ..., a[j-k]) >= a[j] * a[i].
Да, идея абсолютно правильная (первый ее дал watchmaker). Про реализацию. В полном решении хорошо бы учесть, что числа поступают по одному (например из файла):
Входные данные представлены следующим образом. В первой строке задаётся число N — общее количество элементов последовательности. Гарантируется, что N > 8. В каждой из следующих N строк задаётся одно неотрицательное целое число – очередной элемент последовательности.
Т.е. хорошо бы сделать пример использования max_product, который не использует O(N) памяти. В вашем коде используется как раз список размером N. И прямое использование max_product приведет с чтению чисел в список, что сразу же даст 3 балла вместо 4.
Здравствуйте, Serg27, Вы писали:
S>Здравствуйте, crawling-web-crawler, Вы писали: CWC>>Ищем максимум от произведения текущего элемента (за окном справа) на максимум из просмотренных (за окном слева). Если ответ N это произведение a[i] * a[j] при i + k <= j, мы найдем решение, просматривания элемент с индексом j, потому что a[j] * max(a[0], ..., a[j-k]) >= a[j] * a[i].
S>Да, идея абсолютно правильная (первый ее дал watchmaker). Про реализацию. В полном решении хорошо бы учесть, что числа поступают по одному (например из файла): S>
S>Входные данные представлены следующим образом. В первой строке задаётся число N — общее количество элементов последовательности. Гарантируется, что N > 8. В каждой из следующих N строк задаётся одно неотрицательное целое число – очередной элемент последовательности.
S>Т.е. хорошо бы сделать пример использования max_product, который не использует O(N) памяти. В вашем коде используется как раз список размером N. И прямое использование max_product приведет с чтению чисел в список, что сразу же даст 3 балла вместо 4.
Меня интересовала сама алгоритмическая задача, а это несущественные детали реализаци. Если нужно, можно хранить k элементов в циклическом буфере, откуда последний элемент будет уходить для перерасчета максимума просмотренных элементов.
E>Я же про то и написал, что в моём решении уже не понятно, куда лучше. Типа за снижение расхода памяти с 18 int'ов до 8-9 бороться?
В проверке ЕГЭ — все просто.
Есть доки для экспертов, где совершенно однозначно нкаписано, за что давать максимум.
Это линейный алгоритм и массив минимального размера.
При этом прописан довольно большой список возможных ошибок\описок, за которые снижать не нужно.
Твое решение тянет на 3 балла. E>Ну, то есть, вот ты пишешь какую-то контрольную/экзамен/собеседование и т. д, придумал такое решение. Что дальше делать, искать решение лучше или переходить к другим задачкам, или говорить, что готов?
Вот на устном экзамене я без вопросов поставил бы 5 баллов, пообсуждал бы решение вместе с тобой, поискали бы, можно ли лучше.
А на ЕГЭ — не более 3 баллов.
Ибо вложенные циклы есть. И массив не минимального размера.
Поэтому на письменном ЕГЭ-контрольной искать лучше. На устном — можно сказать, что готов.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, Serg27, Вы писали: S>Вчера вечером дочка попросила помочь с задачей из экзамена ЕГЭ по информатике, к которому она готовится. В школе никто из них не смог, преподаватель сказал что-то умное — и его никто не понял. Язык — Python. Я сначала воспринял задачу на слух и решил
S>[q] S>Для заданной последовательности неотрицательных целых чисел необходимо найти максимальное произведение двух её элементов, номера которых различаются не менее чем на 8. Значение каждого элемента последовательности не превышает 1000. Количество элементов последовательности не превышает 10000.
Пардон, только что заметил забавную задачку. И не понял, почему никто не предложил такой вариант? Его можно и по памяти прооптимизировать, но уже лень.
# -*- coding: utf-8 -*-
import numpy as np
s = np.array([10, 100, 45, 55, 245, 35, 25, 10, 10, 10, 26])
result = 0
max_prev = s[0]
for i in range(8, len(s)):
result = max(result, s[i] * max_prev)
max_prev = max(max_prev, s[i - 7])
print(result)
Oпс. Плохо искал. У crawling-web-crawler ровно такое. Sorry.
Здравствуйте, Андрей Ушаков, Вы писали: АУ>Пардон, только что заметил забавную задачку. И не понял, почему никто не предложил такой вариант? Его можно и по памяти прооптимизировать, но уже лень. АУ>Oпс. Плохо искал. У crawling-web-crawler ровно такое. Sorry.
Вы оптимизировали по времени, но не по памяти. Получили бы на ЕГЭ 3 балла вместо 4. Но и не 2 балла, если бы привели прямой решение с O(N*N) по времени.
Здравствуйте, Serg27, Вы писали:
S>Здравствуйте, Андрей Ушаков, Вы писали: АУ>>Пардон, только что заметил забавную задачку. И не понял, почему никто не предложил такой вариант? Его можно и по памяти прооптимизировать, но уже лень. АУ>>Oпс. Плохо искал. У crawling-web-crawler ровно такое. Sorry.
S>Вы оптимизировали по времени, но не по памяти. Получили бы на ЕГЭ 3 балла вместо 4. Но и не 2 балла, если бы привели прямой решение с O(N*N) по времени.
Я же написал, что можно и по памяти (нужно хранить лишь последние 8 элементов в collections.deque), но лень же. Ну, если настаиваете:
# -*- coding: utf-8 -*-
from collections import deque
from io import StringIO
file = StringIO('10\n100\n45\n55\n245\n35\n25\n10\n10\n10\n26\n')
with file:
n = int(file.readline())
result = 0
max_prev = int(file.readline())
container = deque([int(file.readline()) for i in range(7)])
for _ in range(n-8):
this = int(file.readline())
result = max(result, this*max_prev)
max_prev = max(max_prev, container.popleft())
container.append(this)
print(result)
int solve() {
W> const int d = 8;
W> int b[d] = {0};
W> int n = get_next_int();
W> int r = 0;
W> int m = 0;
W> for (int i = 0; i < n; ++i) {
W> int& e = b[i % d];
W> m = max(m, e);
W> e = get_next_int();
W> r = max(r, m * e);
W> }
W> return r;
W>}
Переписал на C# как смог:
Скрытый текст
int Solve(IEnumerable<int> numbers)
{
var enumerator = numbers.GetEnumerator();
const int d = 8;
int[] b = new int[d];
int n = GetNextInt(enumerator);
int r = 0;
int m = 0;
for (int i = 0; i < n; ++i)
{
ref int e = ref b[i % d];
m = Math.Max(m, e);
e = GetNextInt(enumerator);
r = Math.Max(r, m * e);
}
return r;
}
int GetNextInt(IEnumerator<int> enumerator)
{
enumerator.MoveNext();
return enumerator.Current;
}
На исходной последовательности 10, 100, 45, 55, 245, 35, 25, 10, 10, 10, 26 всё отлично, результат = 2600.
На обратной последовательности 26, 10, 10, 10, 25, 35, 245, 55, 45, 100, 10 код падает (InvalidOperationException: Enumeration already finished)
На последовательности 2, 5, 2, 2, 2, 2, 2, 2, 2, 1 выдаёт 0, правильный ответ 5.
У кого косяк?
--
Мой вариант на C#
const int MIN_DISTANCE = 8;
int Solve(IEnumerable<int> numbers)
{
int firstNumber = -1;
int maxProduct = -1;
var queue = new Queue<int>(MIN_DISTANCE + 1);
foreach (int secondNumber in numbers)
{
queue.Enqueue(secondNumber);
if (queue.Count <= MIN_DISTANCE)
{
continue;
}
firstNumber = Math.Max(firstNumber, queue.Dequeue());
maxProduct = Math.Max(maxProduct, firstNumber * secondNumber);
}
return maxProduct;
}
На тех же последовательностях даёт 2600, 2600 и 5.
Здравствуйте, alexzzzz, Вы писали:
A>У кого косяк?
Нужно в условии задачи перечитать часть про формат входных данных.
Тут определённо наблюдается путаница между последовательностью чисел и тем как она представляется.
A>На последовательности 2, 5, 2, 2, 2, 2, 2, 2, 2, 1 выдаёт 0, правильный ответ 5.
Этот вход запрещён условиями задачи.
A>На исходной последовательности 10, 100, 45, 55, 245, 35, 25, 10, 10, 10, 26 всё отлично A>На обратной последовательности 26, 10, 10, 10, 25, 35, 245, 55, 45, 100, 10 код падает
Если развернуть последовательности чисел задом наперёд, то для для входа 10, 100, 45, 55, 245, 35, 25, 10, 10, 10, 26 обратным будет 10, 26, 10, 10, 10, 25, 35, 245, 55, 45, 100 (и наоборот), а не указанный в цитате.
Здравствуйте, watchmaker, Вы писали:
A>>У кого косяк? W>Нужно в условии задачи перечитать часть про формат входных данных. W>Тут определённо наблюдается путаница между последовательностью чисел и тем как она представляется.
Здравствуйте, LaptevVV, Вы писали:
LVV>А на ЕГЭ — не более 3 баллов. LVV>Ибо вложенные циклы есть. И массив не минимального размера.
Интересно, а если бы цикл был невложенный но
for k, j in itertools.combinations(range(9),2):
# тут поиск наибольшего произведения при условии достаточного расстояния
?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском