Ну, для початку припустимо, що ми використовуємо квадрат.
1 2 3
2 3 4
3 4 5
1. Пошук квадрата
Я б використав двійковий пошук по діагоналі. Мета - знайти меншу кількість, яка не є строго нижчою за цільову.
Скажімо, я шукаю, 4
наприклад, тоді я в кінцевому підсумку знайду 5
в (2,2)
.
Тоді, я впевнений , що якщо 4
в таблиці, знаходиться в положенні або (x,2)
або (2,x)
з x
в [0,2]
. Ну, це лише 2 двійкові пошукові запити.
Складність не лякає: O(log(N))
(3 двійкові пошуки за діапазонами довжини N
)
2. Пошук прямокутника, наївний підхід
Звичайно, стає дещо складніше, коли N
і M
відрізняються (за допомогою прямокутника), розглянемо цей вироджений випадок:
1 2 3 4 5 6 7 8
2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17
І скажімо, я шукаю 9
... Діагональний підхід все ще хороший, але визначення діагональних змін. Ось моя діагональ [1, (5 or 6), 17]
. Скажімо, я взяв [1,5,17]
, тоді я знаю, що якщо 9
є в таблиці, це або в підрозділі:
5 6 7 8
6 7 8 9
10 11 12 13 14 15 16
Це дає нам 2 прямокутники:
5 6 7 8 10 11 12 13 14 15 16
6 7 8 9
Тож ми можемо повторити! можливо, починаючи з того, що має менше елементів (хоча в цьому випадку це вбиває нас).
Слід зазначити, що якщо один із вимірів менше 3
, ми не можемо застосовувати діагональні методи і повинні використовувати двійковий пошук. Тут це означало б:
- Застосувати двійковий пошук
10 11 12 13 14 15 16
, не знайдено
- Застосувати двійковий пошук
5 6 7 8
, не знайдено
- Застосувати двійковий пошук
6 7 8 9
, не знайдено
Це складно, тому що для отримання хороших показників ви можете розрізняти кілька випадків, залежно від загальної форми ....
3. Пошук у прямокутнику, жорстокий підхід
Було б набагато простіше, якби ми мали справу з квадратом ... тож давайте просто вирівняємо речі.
1 2 3 4 5 6 7 8
2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17
17 . . . . . . 17
. .
. .
. .
17 . . . . . . 17
Зараз у нас є квадрат.
Звичайно, ми, мабуть, фактично НЕ будемо створювати ці рядки, ми могли б просто наслідувати їх.
def get(x,y):
if x < N and y < M: return table[x][y]
else: return table[N-1][M-1] # the max
тому він поводиться як квадрат, не займаючи більше пам'яті (ціною швидкості, мабуть, залежно від кеш-пам'яті ... ну добре: p)
[[1 1][1 1]]
:?