Якщо припустити, що існує хоча б одна пара елементів, що задовольняє умовам, і множення двох елементів у ній не переповнюється, це можна зробити в 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 - сортування знищить початкові відносини "на відстань".