Да
Вы знаете, что элемент находится внутри индекса [0,i]
первого списка или [0,i]
второго списка. Возьмите элемент i/2
из каждого списка и сравните. Продолжить путем деления пополам.
Я не включаю код, потому что эта проблема очень похожа на домашнюю работу.
РЕДАКТИРОВАТЬ: бисекция является методом бинарного поиска. Это работает так:
Предположим, я = 10; (индексирование на основе нуля, мы ищем 11-й элемент в целом).
На первом шаге вы знаете, что ответ либо в списке 1 (0 ... 10), либо в списке 2 (0 ... 10). Возьмите a = list1 (5) и b = list2 (5).
Если a> b, то в списке list1 есть 5 элементов, предшествующих a, и, по крайней мере, 6 элементов в list2, предшествующих a. Таким образом, a является верхней границей результата. Аналогично, в списке list2 есть 5 элементов, предшествующих b, и менее 6 элементов в list1, предшествующих b. Таким образом, b является нижней границей результата. Теперь мы знаем, что результат находится либо в list1 (0..5), либо в list2 (5..10). Если a
Мы просто повторяем этот процесс, сокращая размер пространства поиска пополам на каждом шаге. Разделение пополам относится к тому факту, что мы выбираем средний элемент (биссектриса) из диапазона, который, как мы знаем, включает в себя результат.
Таким образом, единственное различие между этим и двоичным поиском состоит в том, что в двоичном поиске мы сравниваем со значением, которое ищем, но здесь мы сравниваем со значением из другого списка.
ПРИМЕЧАНИЕ: это на самом деле O(log i)
, что лучше (по крайней мере, не хуже), чем O(log n)
. Кроме того, для малых i (возможно, i <100) было бы на самом деле меньше операций по объединению первых элементов i (линейный поиск вместо деления пополам), потому что это намного проще. Когда вы добавляете в поведение кеша и локальность данных, линейный поиск может быть быстрее для меня до нескольких тысяч. </p>
Кроме того, если i> n, то полагаться на то, что результат должен быть ближе к концу любого списка, ваш начальный диапазон кандидатов в каждом списке от ((i-n) .. n)