#arrays #algorithm
#массивы #алгоритм
Вопрос:
Предположим, что у нас есть 2 отсортированных массива целых чисел A и B и заданный интервал [L, M] . Если x является элементом A, а y — элементом B , наша задача — найти все пары (x, y), которые обладают следующим свойством: L<=y-x<=M. Какой алгоритм наиболее подходит для этой цели?
До сих пор я рассматривал следующее решение: грубая сила. Проверьте разницу всех возможных пар элементов с помощью двойного цикла.Сложность O(n ^ 2).
Немного отличающаяся версия предыдущего решения заключается в использовании того факта, что массивы сортируются, не проверяя элементы A , как только разница выходит за пределы интервала .Сложность все равно будет O (n ^ 2), но, надеюсь, наша программа будет работать быстрее в среднем случае.
Однако я считаю, что O (n ^ 2) не является оптимальным .Есть ли алгоритм с большей сложностью?
Комментарии:
1. Не могли бы вы уточнить в своем вопросе, когда вы ссылаетесь на x, y, L и M в качестве их индекса или значения по этому индексу? Небольшой пример (всего 5 или 6 значений в каждом массиве) также действительно помог бы.
2. Чтобы привести пример, давайте предположим, что A = {1,2,3} , B = {10,12,15} , L = 12, M = 14. Мы хотим 12<=y-x <= 14 (x — элементы A , y — элементы B) . В нашем случае правильными парами являются (1,15) и (2,15) , потому что 12<= 15-1<= 14 и 12<=15-2<=14 . Все другие возможные пары не подходят.
Ответ №1:
Вот решение.
Иметь указатель в начале каждого массива, скажем, i
для массива A и j
для массива B.
Вычислите разницу между B [j] и A [i].
Если она меньше L
, увеличьте указатель в массиве B[], т.е. увеличьте j
на 1
Если это больше M
, увеличьте i
, т.е. указатель на A.
Если разница между ними, то выполните следующее:
-
поиск позиции элемента, значение которого
B[j]-A[i]-L
или ближайшего элемента, значение которого меньше, чем(B[j]-A[i])-L
в массиве A. Это занимаетO(logN)
время. Скажем, позицияp
. Увеличьте количество пар (x, y) наp-i 1
-
Увеличить только указатель
j
Мое решение подсчитывает только количество возможных пар (x, y) за O(NlogN)
время
Для A=[1,2,3]
и B=[10,12,15]
и L=12
и M=14
ответ 3
.
Надеюсь, это поможет. Я оставляю это на ваше усмотрение, для реализации решения
Редактировать: Перечисление всех возможных пар (x, y) заняло бы O(N^2)
наихудшее время. Мы сможем вернуть количество таких пар (x, y) за O(NlogN)
время. Извините, что не разъяснил это раньше.
Правка 2: я прилагаю пример реализации предложенного мной метода ниже:
def binsearch(a, x):
low = 0
high = len(a)-1
while(low<=high):
mid = (low high)/2
if a[mid] == x:
return mid
elif a[mid]<x:
k = mid
low = low mid
else:
high = high - mid
return k
a = [1, 2, 3]
b = [10, 12, 15, 16]
i = 0
j = 0
lenA = len(a)
lenB = len(b)
L = 12
M = 14
count = 0
result = []
while i<lenA and j<lenB:
if b[j] - a[i] < L:
j = j 1
elif b[j] - a[i] > M:
i = i 1
else:
p = binsearch(a,b[j]-L)
count = count p - i 1
j = j 1
print "number of (x,y) pairs: ", count
Комментарии:
1. Могу я задать вопрос? Это может быть просто, но я чего-то не хватает.
2. «Если разница между ними, то сохраните текущую пару, то есть A [i] и B [j]» . После того, как я сохраню эту пару, каким должен быть мой следующий шаг? Если я решу увеличить либо i, либо j, я боюсь, что могу потерять некоторые пары.
3. O (nlogn) определенно намного лучше, чем O (n ^ 2) . Ответ был действительно очень полезен! Спасибо! Может ли существовать алгоритм O (n)?
Ответ №2:
Поскольку каждая комбинация может находиться в указанном диапазоне, наихудшим вариантом является O([A] [B]), что в основном равно O(n ^ 2)
Однако, если вам нужен лучший простой алгоритм, это то, что я придумал. Он запускается аналогично алгоритму пользователя targaryen, но обрабатывает перекрытия упрощенным способом
Create three variables: x,y,Z and s (set all to 0)
Create a boolean 'success' and set to false
Calculate Z = B[y] - A[x]
if Z < L
increment y
if Z >= L and <= M
if success is false
set s = y
set success = true
increment y
store x,y
if Z > M
set y = s //this may seem inefficient with my current example
//but you'll see the necessity if you have a sorted list with duplicate values)
//you can just change the A from my example to {1,1,2,2,3} to see what I mean
set success = false
пример:
A = {1,2,3,4,5}
B = {3,4,5,6,7}
L = 2, M = 3
В этом примере первая пара — x,y . Второе число равно s. Третья пара — это значения A[x] и B[y]. Четвертое число — это Z, разница между A[x] и B[y]. Конечное значение равно X для не совпадения и O для совпадения
0,0 - 0 - 1,3 = 2 O
increment y
0,1 - 0 - 1,4 = 3 O
increment y
0,2 - 0 - 1,5 = 4 X
//this is the tricky part. Look closely at the changes this makes
set y to s
increment x
1,0 - 0 - 2,3 = 1 X
increment y
1,1 - 0 - 2,4 = 2 O
set s = y, set success = true
increment y
1,2 - 1 - 2,5 = 3 O
increment y
1,3 - 1 - 2,6 = 4 X
set y to s
increment x
2,1 - 1 - 3,4 = 1 X
increment y
2,2 - 1 - 3,5 = 2 O
set s = y, set success = true
increment y
2,3 - 2 - 3,6 = 3 O
... and so on