I'm doing this leetcode problem: https://leetcode.com/problems/find-k-pairs-with-smallest-sums/
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.
Find the k pairs (u1,v1),(u2,v2) ...(uk,vk) with the smallest sums.
Input: nums1 = [1,7,11], nums2 = [2,4,6], k = 3
Output: [[1,2],[1,4],[1,6]]
Explanation: The first 3 pairs are returned from the sequence:
[1,2],[1,4],[1,6],[7,2],[7,4],[11,2],[7,6],[11,4],[11,6]
So my thinking process is to use a HashMap, and a Heap. My HashMap's key is the sum of 2 array's index values. And the value, I will put the 2 values that add up to the sum.
Then I add the sums into the heap, then pop it out K times. That will give me the lowest sums.
Now my problem is that when I try to add the hashmap's value into an ArrayList, it gives me an error. Below is what I have tried.
public List<List<Integer>> kSmallestPairs(int[] nums1, int[] nums2, int k) {
List<List<Integer>> ans = new ArrayList<>();
List<Integer> list = new ArrayList<>();
HashMap<Integer, int[]> map = new HashMap<>();
PriorityQueue<Integer> minHeap = new PriorityQueue<>();
for (int i = 0; i < nums1.length; i++) {
for (int j = 0; j < nums2.length; j++) {
int sum = nums1[i] + nums2[j];
map.put(sum, new int[]{nums1[i], nums2[j]});
minHeap.offer(sum);
}
}
for (int i = 0; i < k; i++) {
int key = minHeap.poll();
//list.add(map.get(key)); // ERRORRR
list.add(map.get(key)[0]); //gets the first value associated with key
list.add(map.get(key)[1]); // gets the second value associated with key
}
ans.add(list);
return ans;
}
After researching, the error is because the arraylist has Integer values while my HashMap, I put it as int[]. After searching a bit more, I found
list.add(map.get(key)[0]);
list.add(map.get(key)[1]);
But after doing this, I got the list to show up as: [[1,2,1,4,1,6]].
But I want the answer as: [[1,2],[1,4],[1,6]].
Is there any way to get my list to keep adding a new list? If that makes sense.
Thank you, everyone!
You may use directly List<Integer>
as value of your map to get it easily and put it directly into the result List
:
static List<List<Integer>> kSmallestPairs(int[] nums1, int[] nums2, int k) {
List<List<Integer>> ans = new ArrayList<>();
HashMap<Integer, List<Integer>> map = new HashMap<>();
PriorityQueue<Integer> minHeap = new PriorityQueue<>();
for (int val1 : nums1) {
for (int val2 : nums2) {
int sum = val1 + val2;
map.put(sum, Arrays.asList(val1, val2));
minHeap.offer(sum);
}
}
for (int i = 0; i < k; i++) {
int key = minHeap.poll();
ans.add(map.get(key));
}
return ans; // [[1, 2], [1, 4], [1, 6]]
}
With Java 8 Stream
you could even add a shorter way for the loop at the end (replace the for-i loop)
return IntStream.range(0, k).map(e -> minHeap.poll()).mapToObj(map::get)
.collect(Collectors.toList());
And when you get crazy with Stream
and don't really care about performances, you could do ... :
import static java.util.Arrays.asList;
import static java.util.Comparator.comparingInt;
import static java.util.stream.Collectors.toList;
import static java.util.stream.IntStream.of;
static List<List<Integer>> kSmallestPairs(int[] nums1, int[] nums2, int k) {
return of(nums1)
.mapToObj(v1 -> of(nums2).mapToObj(v2 -> asList(v1, v2)).collect(toList()))
.flatMap(List::stream)
.sorted(comparingInt(o -> o.stream().mapToInt(i -> i).sum()))
.limit(k).collect(toList());
}