Алгоритм поиска минимального количества ходов, требуемых для приведения всех элементов к одному числу (Python)

Прошу помочь решить задачу или хотя бы намекнуть, в какую сторону "копать". Дан массив целых чисел. Необходимо найти минимальное количество ходов, требуемых для приведения всех элементов массива к одному числу. За один ход можно уменьшить или увеличить один элемент массива на 1. Все достаточно просто пока массив выглядит вот так:

`
import math


nums = [1, 10, 2, 9]
result_digit = math.ceil((max(nums))/2)
count = 0
for id, i in enumerate(nums):
    while i != result_digit:
        if i < result_digit:
            i += 1
            count += 1
         elif i > result_digit:
             i -= 1
             count += 1
         else:
            nums[id] = i
    print(count)
`

Но, если nums = [0, 0, 0, 1], тогда этот алгоритм не подходит и выведет результат 3 вместо 1. Массив может быть любой длинны.


Ответы (2 шт):

Автор решения: CrazyElf

Ну, во-первых округлять нужно с помощью round, у вас получается не оптимальное округление, не к ближайшему целому. А во-вторых - почему max/2? Приводить нужно к среднему арифметическому:

result_digit = round(sum(nums)/len(nums))

Можете проверить на примере, где все числа далеки от нуля. Ваш вариант начнёт приводить куда-то вообще не туда. Например, если взять:

nums = [9, 9, 9, 10]

Ваш вариант начнёт приводить всё к 10/2, т.е. 5, а не к округлённому среднему 9, как было бы оптимально.

→ Ссылка
Автор решения: Stanislav Volodarskiy

Посмотрим на задачу с конца. Если мы как-то узнали значение m к которому нужно привести массив, то сколько на это уйдет шагов? Для одного элемента массива a[i] потребуется abs(a[i] - m) шагов. Для всего массива sum(abs(v - m) for v in a).

Известно что минимум суммы выше будет достигаться если m медиана a. Медиан может быть много. Одна из медиан - средний элемент массива после его сортировки.

a = [1, 10, 2, 9]
m = sorted(a)[len(a) // 2]
print(sum(abs(v - m) for v in a))
16
→ Ссылка