Что ж, для начала предположим, что мы используем квадрат.
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]]
:?