1 Востаннє редагувалося leofun01 (26.02.2025 05:21:26)

Тема: Collections binary search з порівнятором

Дано перелік цілих чисел і задане число. Потрібно знайти кількість пар чисел, сума елементів яких менше заданого числа.
Другий елемент пари обов'язково має стояти після першого в цьому переліку.
Я намагаюся використати бінарний пошук із колекцій, але щось в мене не виходить. Просто не розумію як правильно докупи все зібрати.

class Solution {
    public int countPairs(List<Integer> nums, int target) {
        Collections.sort(nums);
        int answer = 0;
        record Num_Pair(Integer target, Integer num) {
        }
        ;
        Comparator<Num_Pair> cmp = new Comparator<Num_Pair>() {
            public int compare(Num_Pair first, Num_Pair second) {
                if (first.target - second.num < 2) {
                    return 1;
                } else {
                    return -1;
                }
            }
        };
        for (int i = 0; i < nums.size(); ++i) {
            List<Integer> new_list = new ArrayList<>();
            new_list = nums.subList(i, nums.size() - 1);
            Num_Pair new_pair;
            new_pair.target = target;
            new_pair.num = nums.get(i);
            int index = Collections.binarySearch(new_list, new_pair, cmp);
            if (index > 0) {
                ++answer;
            }
        }
        return answer;
    }
}

2

Re: Collections binary search з порівнятором

Ось таке працює, хоч і без колекцій:

class Solution {
    public int countPairs(List<Integer> nums, int target) {
        Collections.sort(nums);
        int answer = 0;
        int left = 0;
        int right = nums.size() - 1;
        while (left < right) {
            int number = nums.get(left) + nums.get(right);
            if (number < target) {
                answer += right - left;
                System.out.println(left + " " + right);
                ++left;
            } else {
                --right;
            }
        }

        return answer;
    }
}

Я так розумію бінарний пошук із колекцій краще брати
лише якщо треба визначити наявність чи відсутність елемента.
У решті випадків простіше самому написати.

3

Re: Collections binary search з порівнятором

Я давно з жабою не працював; але якщо дійсно Collections.binarySearch потребує пар чисел (що дивно, бо nums ніби List<Integer>, а не List<Num_Pair>), то все одно питання про кількість пар, а не кількість чисел, що можуть бути меншим елементом пари, тобто треба робити щось на кшталт
answer += index;
(Уважно прочитайте https://docs.oracle.com/javase/7/docs/api/java/util/Collections.html, щоб розібратися, як саме обробляти випадки, коли число є в списку і коли нема)
Але порівнювати ж треба не на різницю з 2, а на різницю між числами, щоб була меншою за target. І взагалі вам кастомний компаратор не потрібен, достатньо nums[i] + target бінарним пошуком шукати.

Подякували: Teg Miles, leofun012

4

Re: Collections binary search з порівнятором

Ну і так, тут бінарний пошук не потрібен, він тільки підвищує складність (не враховуючи сортування). Сортування дає O(nlog(n)), а пошук потім з бінарним O(nlog(n)), а без нього O(n).

5 Востаннє редагувалося koala (25.02.2025 09:35:07)

Re: Collections binary search з порівнятором

Не розумію, як ваш алгоритм працює. Припустимо, маємо числа {1,2,3} і target=2. Кількість пар=2.
Починаємо з left=0, right=2,
1 ітерація. number = 4, right стає 1.
2 ітерація. number = 3, right стає 0.
Умова left<right більше не виконується. Знайдено 0 пар.
Вам натомість треба якось так:

sort(nums)
answer=left=right=0
while left<right:
    while right<nums.size() || nums.get(right)-nums.get(left)<target:
        right++
    answer += right-left+1
    left++

6

Re: Collections binary search з порівнятором

koala написав:

Ну і так, тут бінарний пошук не потрібен, він тільки підвищує складність (не враховуючи сортування). Сортування дає O(nlog(n)), а пошук потім з бінарним O(nlog(n)), а без нього O(n).

Знаю, там за допомогою 2 вказівників можна вирішити.
Але Літкод сказав бінарний пошук, отже, бінарний пошук:).
Намагаюся вивчити стандартну бібліотеку Джави за допомогою Літкода.

7 Востаннє редагувалося Teg Miles (25.02.2025 19:18:49)

Re: Collections binary search з порівнятором

koala написав:

Не розумію, як ваш алгоритм працює. Припустимо, маємо числа {1,2,3} і target=2. Кількість пар=2.
Починаємо з left=0, right=2,
1 ітерація. number = 4, right стає 1.
2 ітерація. number = 3, right стає 0.
Умова left<right більше не виконується. Знайдено 0 пар.
Вам натомість треба якось так:

sort(nums)
answer=left=right=0
while left<right:
    while right<nums.size() || nums.get(right)-nums.get(left)<target:
        right++
    answer += right-left+1
    left++

У вашому прикладі немає жодної пари, чия сума була б менше двох.
Правий і лівий треба додавати, а не віднімати.
Моя провина, я в описі помилився, там про суму йшлося.
Ось це воно: https://leetcode.com/problems/count-pai … scription/