2

The question is this:

You are given two integer arrays nums1 and nums2 sorted in ascending order and an integer k.

Define a pair (u, v) which consists of one element from the first array and one element from the second array.

Return the k pairs (u1, v1), (u2, v2), ..., (uk, vk) with the smallest sums.

My first idea was to find all the sums, and then add it to a minheap, but the time complexity for that is very large I think O(n^2logn).

I can't understand how to optimize the solution to make it faster.

Here is my code for going through all iterations of possible sums then adding them to a min heap. I was wondering how to optimize this code to make it run in O(nlogn).

public List<List<Integer>> kSmallestPairs(int[] nums1, int[] nums2, int k) {
     HashMap<ArrayList<Integer>, Integer> all_values = new HashMap<ArrayList<Integer>, Integer>();
     PriorityQueue<Map.Entry<ArrayList<Integer>, Integer>> k_pairs = new PriorityQueue<Map.Entry<ArrayList<Integer>, Integer>>(
     (a,b) -> b.getValue().compareTo(a.getValue())
     );
     for(int i = 0; i < nums1.length; i++){
        for(int j = 0; j <  nums2.length; j++){
            ArrayList<Integer> temp = new ArrayList<Integer>();
            temp.add(i);
            temp.add(j);
            all_values.put(temp, nums1[i] + nums2[j]);

        }
     }
        
    for(Map.Entry<ArrayList<Integer>, Integer> o : all_values.entrySet()){
        k_pairs.offer(o);
        if(k_pairs.size() > k){
            k_pairs.poll();
        }
    }
        
    List<List<Integer>> final_all_k = new ArrayList<List<Integer>>();
    while(k_pairs.size() > 0){
        List<Integer> temp = k_pairs.poll().getKey();
        int temp_index1 = nums1[temp.get(0)];
        int temp_index2 = nums2[temp.get(1)];
        temp.clear();
        temp.add(temp_index1);
        temp.add(temp_index2);
        final_all_k.add(temp);
        
    }
    
     return final_all_k;
}
Dillon Davis
  • 6,679
  • 2
  • 15
  • 37
  • Is it not just picking the first k elements from each sorted list and forming pairs? Unless you can pick an element multiple times from each list. – SomeDude May 11 '22 at 02:11
  • I thought of that, but wouldn't the time complexity of that be O(k^2logn) I've read that the best time complexity for this should be O(nlogn) –  May 11 '22 at 02:34
  • I don't understand, the time complexity for what SomeDude suggested is O(n), where n = k, and I can't think of a counterexample where that wouldn't work. Just take the first k entries from each array and pair them up. Can you show a case where that doesn't give you the k smallest pairs? – David Conrad May 11 '22 at 03:15
  • @DavidConrad how will you pair up `k` numbers in `O(k)`? – Abhinav Mathur May 11 '22 at 03:51
  • Have you considered the idea? , without loss of generality take the list nums1 and for each element x in this array you will do binary search in the second array nums2 such that the element you are looking for is the closest to element x. Calculate the difference and keep the smallest difference. – Gerardo Gonzalez - Nemis May 11 '22 at 04:44
  • What are the ranges for `n` and `k`? If `k` is small (in 1000s), `k^2` algorithm should work fine. – vish4071 May 11 '22 at 05:13
  • @k9vok It is just O(n) or O(k) if the lists are already sorted. You need to pick an element from each list and form a pair like (a0,b0),(a1,b1)...(ak,bk). If the lists are not sorted, then you sort them. Then the complexity is O(nlogn) – SomeDude May 11 '22 at 13:20
  • As others have said, it is O(k) because you only need to look at the first k numbers, and you only look at each once. How would it be anything other than O(k)? Please show us an example of numbers where you can't just pair nums1[0], nums2[0]; nums1[1], nums2[1], etc. – David Conrad May 11 '22 at 18:31

1 Answers1

0

Assuming the following is in fact your objective (that I'm not misinterpreting your question):

Minimize: max(u1 + v1, u2 + v2, ..., uk + vk)

You can simply take the first k elements of each list (which will be the smallest k of each), reverse one of the sublists, and pair them.


Proof

We can ignore the latter n-k elements because if any of those elements were used in the "smallest" pairs, we'd just swap that value out for an unused element in the first k elements, for a smaller valued pair.

We can group them up by reversing one sublist and pairing because this is optimal. To make this obvious, consider some variables a, b, c, and d. Lets say we pair them up like: (b, d), (a, c), we could also write this out:

list1: ..., b, a, ...
list2: ..., d, c, ...

Now, suppose that I tell you that c < d and a < b. Since list2 is reversed, c < d would put d before c, just like we have it- good. But a < b would imply that a should precede b, which it does not. For any such inversion, we can safely invert the two elements for a smaller sum.

list1: ..., a, b, ...
list2: ..., d, c, ...

This results in the pairs (a, d) and (b, c), so R2 = max(..., a+d, b+c, ...) instead of R1 = max(..., b+d, a+c, ...). Now, we said that a < b and c < d, so a+c < b+d, so R1 = max(..., b+d, ...). We can also simplify R2, by substituting a with b (since a < b) and c with d (since c < d), giving

R2 = max(..., a+d, b+c, ...) < max(..., b+d, b+d, ...) = max(..., b+d, ...) = R1

So R2 < R1, our inversion reduced the max sum.

Repeating this until there's no inversions left, we're left with two sorted sublists- one in ascending order, and one descending.

Dillon Davis
  • 6,679
  • 2
  • 15
  • 37
  • 2
    The objective you're assuming seems to be different from OP's question – Abhinav Mathur May 11 '22 at 06:00
  • @AbhinavMathur would you mind clarifying? It seemed too trivial, hence why I outlined it explicitly, but I can't find another reasonable way to interpret it. – Dillon Davis May 11 '22 at 07:30
  • If OP meant distinct pairs with repetition, they wouldn't/shouldn't use distinct indices `v1`/`v2`/`v3` etc. because that implies they're different values of the list. But if its not that, I'm not sure what else. – Dillon Davis May 11 '22 at 07:32
  • 1
    I think the numbers just indicate that they are different pairs; it isn't mentioned that the same item can't be used in multiple pairs – Abhinav Mathur May 11 '22 at 07:48
  • @AbhinavMathur If the same item can be used in multiple pairs, all pairs could just be of the first items from each list. Basically, either this problem is trivial and can be easily solved in linear time, or OP hasn't told us what the rules are. We shouldn't have to argue, debate, or guess. – David Conrad May 11 '22 at 18:34
  • 1
    @DavidConrad From both the description and the slow code, the OP wants DISTINCT pairs. So an element can be used in multiple pairs, as long as the other element of the pair is different. – btilly May 11 '22 at 19:33
  • Here's the [original from leetcode](https://leetcode.com/problems/find-k-pairs-with-smallest-sums/), with examples. Note that `k` could be as large as `n²`, which is the number of possible pairs, and that it's possible to find the kth smallest sum in O(n) (although obviously it takes O(k) to list all of the k smallest sums). – rici May 11 '22 at 21:01