#java #algorithm
Вопрос:
Я столкнулся с проблемой кодирования, которая заключается в следующем:
Учитывая 2 отсортированных массива: A и B и положительное целое число x, выведите сумму ближайшей пары (по одной из каждого массива) в x.
Пример:
B = {10,20,30,40} , A = {0,4,6,11,11} , x = 13.
Выходные данные: 4 и 10.
Это то, что я пробовал:
int i = 0;
int j = b.length - 1;
int closest = Integer.MAX_VALUE;
String s = "";
while (i <= a.length - 1 amp;amp; j >= 0)
{
if (Math.abs((b[j] a[i]) - x) < closest || Math.abs((b[j] a[i]) - x) == 0)
{
closest = Math.abs(x - (b[j] a[i]));
s = a[i] " " "and" " " b[j];
if (j != 0)
j--;
}
if (Math.abs((b[j] a[i]) - x) > closest || j == 0)
i ;
}
System.out.println(s);
Этот код отлично работает с большинством входов, которые я протестировал, включая приведенный выше пример,
за исключением случаев, когда вход x
равен 70, а выход-11 и 30 вместо 11 и 40.
В основном я пытаюсь понять, когда мне следует уменьшать j
, а когда увеличивать i
, чтобы код работал на каждом возможном x
входе.
Решение должно быть O(n) временной сложности.
Спасибо за помощь! (Если вы обнаружите ошибки в моем английском, пожалуйста, дайте мне знать, я пытаюсь исправиться.)
Комментарии:
1.https://www.geeksforgeeks.org/given-two-sorted-arrays-number-x-find-pair-whose-sum-closest-x/ ?
Ответ №1:
Вы должны использовать метод двух указателей, чтобы получить желаемый результат. Приведенный ниже код будет работать для вас.
while (i <= a.length-1 amp;amp; j >= 0) {
if (Math.abs((b[j] a[i]) - x ) < closest || Math.abs( (b[j] a[i]) - x) == 0) {
closest = Math.abs(x - (b[j] a[i])) ;
s = a[i] " " "and" " " b[j];
}
if (b[j] a[i] > x) j --;
else i ;
}
Временная сложность определенно O(n).
Для получения подробных инструкций, пожалуйста, посетите веб-сайт GeeksforGeeks.
Ответ №2:
public static int[] getClosestPairSum(int[] A, int[] B, int x) {
TreeSet<Integer> unique = new TreeSet<>();
for (int a : A)
unique.add(a);
int absDiff = -1;
int[] res = { 0, 0 };
for (int b : B) {
for (Integer aa : Arrays.asList(unique.floor(x - b), unique.ceiling(x - b))) {
if (aa == null)
continue;
int curAbsDiff = Math.abs(x - b - aa);
if (absDiff == -1 || curAbsDiff < absDiff) {
absDiff = curAbsDiff;
res[0] = aa;
res[1] = b;
}
}
}
return res;
}
Ответ №3:
В основном похоже на код вопроса (немного проще?):
// returning an array so I can check against brute force algorithm
private static int[] closestPair(int[] a, int[] b, int x) {
int closest = Integer.MAX_VALUE;
int[] result = { -1, -1 }; // could use null
int i = 0;
int j = b.length-1;
while (i < a.length amp;amp; j >= 0) {
int diff= (a[i] b[j]) - x;
// is it closer?
if (abs(diff) < closest) {
closest = abs(diff);
result[0] = a[i];
result[1] = b[j];
}
// which pointer to change for next iteration
if (diff == 0) break; // shortcut, can't get closer
if (diff < 0) {
i ; // sum was less than x, try higher value
} else {
j--; // sum was greater, try a smaller one
}
}
return resu<
}