Якщо припустити, що існує хоча б одна пара елементів, що задовольняє умовам, і множення двох елементів у ній не переповнюється, це можна зробити в Theta(n-k)
часі та Theta(1)
просторі в гіршому та найкращому випадку:
auto back_max = a[0];
auto back_min = a[0];
auto best = a[0]*a[k+1];
for(std::size_t i=1; i<n-(k+1); ++i) {
back_max = std::max(back_max, a[i]);
back_min = std::min(back_min, a[i]);
best = std::min(best, std::min(a[i+k+1]*back_max, a[i+k+1]*back_min));
}
return best;
Це оптимально з точки зору асимптотичної найгіршої складності як для часу, так і для простору, оскільки оптимальний добуток може бути принаймні a[0]
з будь-яким з n-(k+1)
елементів на відстані k+1
, тому принаймні n-(k+1)
цілі числа повинні бути прочитані будь-яким алгоритмом, що вирішує проблему.
Ідея алгоритму полягає в наступному:
Оптимальний продукт використовує два елементи a
, припустимо, що це a[r]
та a[s]
. Без втрати загальності можна вважати, що s > r
оскільки продукт є комутативним.
Через обмеження abs(s-r) > k
це означає, що це s >= k+1
. Тепер s
кожен із показників міг би задовольнити цю умову, тому ми повторимо ці показники. Це ітерація i
у показаному коді, але вона зрушена k+1
для зручності (насправді не має значення). Для кожної ітерації нам потрібно знайти оптимальний продукт, що включає i+k+1
як найбільший індекс, і порівняти його з попередньою найкращою здогадкою.
Можливі індекси, i+k+1
з якими можна поєднатись, - це всі індекси, менші або рівні i
через вимогу відстані. Нам також слід перебрати все це, але це зайве, оскільки мінімум a[i+k+1]*a[j]
перевищення j
при фіксованому i
рівні дорівнює min(a[i+k+1]*max(a[j]), a[i+k+1]*min(a[j]))
монотонності продукту (беручи мінімум щодо мінімального та максимального над a[j]
рахунками для двох можливих ознаки a[i+k+1]
або рівнозначно двох можливих напрямків монотонності.)
Оскільки набір a[j]
значень, над якими ми тут оптимізуємось, справедливий {a[0], ..., a[i]}
, який просто збільшується на один елемент ( a[i]
) у кожній ітерації i
, ми можемо просто відслідковувати max(a[j])
і за min(a[j])
допомогою одних змінних, оновлюючи їх, якщо a[i]
вони більші чи менші за попередні оптимальні значення. Це робиться за допомогою back_max
і back_min
в прикладі коду.
Перший крок ітерації ( i=0
) пропускається в циклі і замість цього виконується як ініціалізація змінних.
std::vector
? @Scheff - сортування знищить початкові відносини "на відстань".