spamsink: (lenin)
[personal profile] spamsink
Есть программистская задачка, на которую я не знаю правильного ответа.

Дан массив чисел. Нужно наиболее эффективным образом найти в нем такой непрерывный подмассив, чтобы среднее значение элементов этого подмассива и среднее значение остальных элементов максимально различались.

Например, пусть дан массив [99, 99, 99, 0, 0, 0, 100, 0, 0, 0].

Если мы возьмем подмассив, состоящий только из элемента 100, то среднее остальных элементов будет 3*99/9 = 33, а разность средних - 100-33 = 67.
Если брать в качестве подмассива группу из трех нулей, то среднее остальных равно (3*99+100)/7 = 56.714..., что хуже.
Если мы возьмем подмассив, состоящий из трех элементов, равных 99, то его среднее будет 99, среднее остальных элементов - 100/7 = 14.285..., а разность - 99-14.285... = 84.714... (максимум).

Но при увеличении количества нулей результат меняется. Пусть массив таков:
[99, 99, 99, (триста нулей), 100, (триста нулей)].

Тогда если взять подмассив [99, 99, 99], получим разность средних 99-100/601 = 98.8..., а если взять подмассив [100], получим 100-3*99/603=99.5..., и в этом случае подмассив [100] оптимален.

Date: 2016-06-29 02:22 am (UTC)
From: [identity profile] rezkiy.livejournal.com
посчитать среднее, мин и макс за один проход. Подмассив из одного элемента в котором мин или подмассив в котором макс будут ответом.

Date: 2016-06-29 02:27 am (UTC)
From: [identity profile] rezkiy.livejournal.com
Вру. Не увидел слова 'остальных'

Date: 2016-06-29 02:39 am (UTC)
From: [identity profile] rezkiy.livejournal.com
да, конечно. Я пропустил очень важное слово.

Date: 2016-06-29 05:19 am (UTC)
vak: (Default)
From: [personal profile] vak
Разве что за N^2 пополам проходов.

Date: 2016-06-29 11:55 am (UTC)
From: [identity profile] yatur.livejournal.com
В таких задачках шаг влево или вправо - и опаньки, линейного решения нет, только полный перебор.

Date: 2016-06-29 05:07 pm (UTC)
From: [identity profile] sab123.livejournal.com
Есть ли некое требование про размер этого подмассива?

Потому что иначе ответ прост:
За один проход находим среднее массива, а так же самое большое и самое маленькое число в нем (и их позиции). Смотрим, что дальше от среднего в массиве - самое большое или самое маленькое число, и соответственно выбираем его как подмассив из 1 элемента.

Чуть более интеллектуальная разновидность: запоминаем не просто самое большое и самое маленькое число, а последовательности из них, и предпочитаем самую длинную последовательность. Вуаля, линейное решение.

Вот если размер подмассива фиксирован - то сложнее.

Date: 2016-06-30 12:44 am (UTC)
From: [identity profile] kcmamu.livejournal.com
Это всё для исправления шрифта надо?
Тогда, подозреваю, более адекватная постановка была бы с поиском не максимальной разницы средних, а минимальной суммы квадратов отличий чисел от соотв. средних.
Edited Date: 2016-06-30 12:44 am (UTC)

Date: 2016-06-30 03:09 am (UTC)
From: [identity profile] archaicos.livejournal.com
Это пахнет проблемой Longest Common Substring, которая решается через Dynamic Programming за квадратичное время.

Date: 2016-06-30 03:40 am (UTC)
From: [identity profile] kcmamu.livejournal.com
Я нечто похожее творил так: берем окрестность пиксела, упорядочиваем все значения по возрастанию яркости и ищем границу в этом упорядоченном списке. Новое значение яркости := среднее по тому подмножеству, куда попал сам этот пиксел. Устроившие меня результаты -- такие, как на картинке (она уменьшена на 50%, а если кликнуть, будет в полный размер):



Должно хорошо работать в тех случаях, когда картинка не слишком зашумлена и типичные "береговые линии" (если всё, что ниже порога, -- море, а выше -- суша) достаточно гладкие, без островков и луж.
Edited Date: 2016-06-30 04:35 am (UTC)

Date: 2016-06-30 06:03 am (UTC)
From: [identity profile] archaicos.livejournal.com
Связь в том, что там пробуют добавить и/или пропустить символ и смотрят от чего разница будет минимальна. Несколько похоже. Но да, среднее портит малину.

Date: 2016-06-30 05:39 pm (UTC)
From: [identity profile] sab123.livejournal.com
Приходит в голову вариант с двумя проходами:

На первом проходе определяем среднее массива.

На втором проходе ищем подмассивы и запоминаем лучший найденный. Начинаем с первого числа и смотрим, больше оно или меньше среднего. Продолжаем добавлять к подмассиву средние числа, пока они находятся с той же стороны от среднего (при переносе каждого числа в подмассив, соответственно корректируем среднее оставшихся в массиве чисел). Если находится число с другой стороны от среднего, то запоминаем эту позицию (в каждый момент может быть запомнено не более одной позиции) и продолжаем пытаться добавить еще чисел, пока не случится одно из (а) среднее подмассива сравнится со средним остального массива или (б) найдется некоторое фиксированное количество X чисел подряд, которые попадают на другую сторону. Если одно их этих условий случается, плюем и отскакиваем на запомненную позицию, где опять начинаем с одного числа в подмассиве.

Введение ограничения числа X ограничивает оптимальность, но и ограничивает время выполнения O(X*N), то есть при малом X выходит O(N).

Date: 2016-06-30 05:48 pm (UTC)
From: [identity profile] sab123.livejournal.com
Пардон, в алгоритм вкралась неточность. Вот исправленный вариант:

На первом проходе определяем среднее массива.

На втором проходе ищем подмассивы и запоминаем лучший найденный. Начинаем с переноса в подмассив первого числа и смотрим, больше оно или меньше среднего. Продолжаем добавлять к подмассиву следующие числа, пока они находятся с той же стороны от среднего в массиве средневзвешенной точки между средним в массиве и средним в подмассиве, вес согласно числе чисел в массиве и подмассиве (при переносе каждого числа в подмассив, соответственно корректируем среднее оставшихся в массиве чисел). Это учловие гарантирует, что при переносе этого числа в подмассив, средние массива и подмассива разойдутся дальше. Если находится число с другой стороны от этой точки, то запоминаем эту позицию (в каждый момент может быть запомнено не более одной позиции) и продолжаем пытаться добавить еще чисел, пока не случится одно из (а) среднее подмассива сравнится со средним остального массива или (б) найдется некоторое фиксированное количество X чисел подряд, которые попадают на другую сторону. Если одно их этих условий случается, плюем и отскакиваем на запомненную позицию, где опять начинаем с одного числа в подмассиве.

Введение ограничения числа X ограничивает оптимальность, но и ограничивает время выполнения O(X*N), то есть при малом X выходит O(N).

Если X=N, то получается в худшем случае квадратичный алгоритм, который находит оптимальную точку.
Edited Date: 2016-06-30 05:49 pm (UTC)

Date: 2016-06-30 06:06 pm (UTC)
From: [identity profile] sab123.livejournal.com
Прогнал через тестовый пример, получается что надо добавить третье условие, когда надо отскочить на запомненную позицию: если достигнут конец массива. Чтобы гарантированно пытаться начинать с каждого перехода через среднее.

И средневзвешенная точка оказывается фиксированной, это среднее изначального полного массива.
Edited Date: 2016-06-30 06:07 pm (UTC)

Date: 2016-06-30 06:37 pm (UTC)
From: [identity profile] sab123.livejournal.com
Да уж, действительно. Я подозреваю, что это можно исправить через более лучший анализ "производной", т.е. как каждое число влияет на среднее. Или может даже "второй производной".

Date: 2016-06-30 08:12 pm (UTC)
From: [identity profile] sin-gular.livejournal.com
А если отсортировать сохраняя массив индексов и пройти по индесам аналогом максимального подмассива?

Date: 2016-06-30 10:29 pm (UTC)
From: [identity profile] sin-gular.livejournal.com
Не полное решение, но с предложенным тестовым примером справится, или я ошибаюсь?
Edited Date: 2016-06-30 10:32 pm (UTC)

Date: 2016-07-02 01:43 am (UTC)
From: [identity profile] sevabashirov.livejournal.com
Чем-то напоминает феномен Уилла Роджерса.

Date: 2016-07-03 12:48 pm (UTC)
From: [identity profile] sin-gular.livejournal.com
Ну допустим если для каждого подмассива считать именно Сумаа/Длина-(ВсяСумма-Сумма)/(ВсяДлина-Длина) с этими тестами справится.
Но [99, 99, 15, 99, 99, 0, 0, 0, 100, 0, 0, 0] уже непройдёт...

Date: 2016-07-04 09:19 pm (UTC)
From: [identity profile] sin-gular.livejournal.com
... что не большая проблема. Если границы искомого отрезка - пересечения границы среднего, а вроде бы оно так, то остальное вопрос техники.

Profile

spamsink: (Default)
spamsink

February 2026

S M T W T F S
12345 67
8 91011 121314
15161718 192021
22 2324 25262728

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Mar. 7th, 2026 10:00 pm
Powered by Dreamwidth Studios