Skip to content

Commit 77d0cb6

Browse files
committed
added problem 373
1 parent 42fad59 commit 77d0cb6

File tree

3 files changed

+147
-0
lines changed

3 files changed

+147
-0
lines changed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package problem0373
2+
3+
import (
4+
"container/heap"
5+
"sort"
6+
)
7+
8+
/*
9+
You are given two integer arrays nums1 and nums2 sorted in ascending order and an integer k.
10+
Define a pair (u, v) which consists of one element from the first array and one element from the second array.
11+
Return the k pairs (u1, v1), (u2, v2), ..., (uk, vk) with the smallest sums.
12+
*/
13+
14+
type Pair struct {
15+
A, B int // Elements
16+
Idx int // Index of the 2nd element
17+
}
18+
19+
func kSmallestPairs(nums1, nums2 []int, k int) [][]int {
20+
var res [][]int
21+
// Priority queue containing the possible pairs
22+
var pq = MakeHeap(MinHeap)
23+
// Pushing all the pairs with nums2[0] as one of the elements
24+
for i := 0; i < k && i < len(nums1); i++ {
25+
heap.Push(pq, Pair{nums1[i], nums2[0], 0})
26+
}
27+
var maxPairs = len(nums1) * len(nums2)
28+
// K can be larger than the maximum possible pairs
29+
// so we need to make sure to exit when no more pairs are
30+
// available
31+
for i := 0; i < k && i < maxPairs; i++ {
32+
// Take smallest pair
33+
cur := heap.Pop(pq).(Pair)
34+
res = append(res, []int{cur.A, cur.B})
35+
// If the 2nd element is not the last one in nums2
36+
// we can consider a new pair with the next element in nums2
37+
if cur.Idx < len(nums2)-1 {
38+
// Push a new pair with the next element in nums2
39+
// and the smallest element in nums1 so far
40+
heap.Push(pq, Pair{cur.A, nums2[cur.Idx+1], cur.Idx + 1})
41+
}
42+
}
43+
return res
44+
}
45+
46+
func kSmallestPairsNaive(nums1, nums2 []int, k int) [][]int {
47+
var res = make([][]int, len(nums1)*len(nums2))
48+
for i := range nums1 {
49+
for j := range nums2 {
50+
res[i*len(nums2)+j] = []int{nums1[i], nums2[j]}
51+
}
52+
}
53+
sort.Slice(res, func(i, j int) bool {
54+
return (res[i][0] + res[i][1]) < (res[j][0] + res[j][1])
55+
})
56+
if k >= len(res) {
57+
return res
58+
}
59+
return res[:k]
60+
}
61+
62+
// Priority queue implementation
63+
type Heap struct {
64+
Values []Pair
65+
LessFunc func(Pair, Pair) bool
66+
}
67+
68+
func (h *Heap) Less(i, j int) bool { return h.LessFunc(h.Values[i], h.Values[j]) }
69+
func (h *Heap) Swap(i, j int) { h.Values[i], h.Values[j] = h.Values[j], h.Values[i] }
70+
func (h *Heap) Len() int { return len(h.Values) }
71+
func (h *Heap) Peek() Pair { return h.Values[0] }
72+
func (h *Heap) Pop() (v interface{}) {
73+
h.Values, v = h.Values[:h.Len()-1], h.Values[h.Len()-1]
74+
return v
75+
}
76+
func (h *Heap) Push(v interface{}) { h.Values = append(h.Values, v.(Pair)) }
77+
78+
func MakeHeap(less func(Pair, Pair) bool) *Heap {
79+
return &Heap{LessFunc: less}
80+
}
81+
82+
func MaxHeap(i, j Pair) bool { return i.A+i.B > j.A+j.B }
83+
func MinHeap(i, j Pair) bool { return i.A+i.B < j.A+j.B }
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package problem0373
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
)
9+
10+
type TestCase struct {
11+
Nums1, Nums2 []int
12+
k int
13+
Expected [][]int
14+
}
15+
16+
var TestCases = []TestCase{
17+
{[]int{1, 7, 11}, []int{2, 4, 6}, 3,
18+
[][]int{{1, 2}, {1, 4}, {1, 6}}},
19+
{[]int{1, 1, 2}, []int{1, 2, 3}, 2,
20+
[][]int{{1, 1}, {1, 1}}},
21+
{[]int{1, 2}, []int{3}, 3,
22+
[][]int{{1, 3}, {2, 3}}},
23+
{[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32},
24+
[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32},
25+
6,
26+
[][]int{{1, 1}, {2, 1}, {1, 2}, {2, 2}, {1, 3}, {3, 1}}},
27+
}
28+
29+
func TestSmallestPairSums(t *testing.T) {
30+
assert := assert.New(t)
31+
32+
for _, tc := range TestCases {
33+
want := tc.Expected
34+
got := kSmallestPairs(tc.Nums1, tc.Nums2, tc.k)
35+
assert.ElementsMatch(want, got, fmt.Sprintf("%+v", tc))
36+
}
37+
}
38+
39+
func BenchmarkSmallestPairSums(b *testing.B) {
40+
for i := 0; i < b.N; i++ {
41+
for _, tc := range TestCases {
42+
kSmallestPairs(tc.Nums1, tc.Nums2, tc.k)
43+
}
44+
}
45+
}
46+
47+
func TestSmallestPairSumsNaive(t *testing.T) {
48+
assert := assert.New(t)
49+
50+
for _, tc := range TestCases {
51+
want := tc.Expected
52+
got := kSmallestPairsNaive(tc.Nums1, tc.Nums2, tc.k)
53+
assert.ElementsMatch(want, got, fmt.Sprintf("%+v", tc))
54+
}
55+
}
56+
57+
func BenchmarkSmallestPairSumsNaive(b *testing.B) {
58+
for i := 0; i < b.N; i++ {
59+
for _, tc := range TestCases {
60+
kSmallestPairsNaive(tc.Nums1, tc.Nums2, tc.k)
61+
}
62+
}
63+
}

readme.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ Each problem is in it's own directory, with test files. There are helper package
179179
| 0349 | [Intersection of Two Arrays](https://leetcode.com/problems/intersection-of-two-arrays) | [My Solution](./problems/problem0349) ||
180180
| 0352 | [Data Stream as Disjoint Intervals](https://leetcode.com/problems/data-stream-as-disjoint-intervals) | [My Solution](./problems/problem0352) ||
181181
| 0363 | [Max Sum of Rectangle No Larger Than ](https://leetcode.com/problems/max-sum-of-rectangle-no-larger-than-k) | [My Solution](./problems/problem0363) ||
182+
| 0373 | [Find K Pairs with Smallest Sums](https://leetcode.com/problems/find-k-pairs-with-smallest-sums/) | [My Solution](./problems/problem0373) ||
182183
| 0374 | [Guess Number Higher or Lower](https://leetcode.com/problems/guess-number-higher-or-lower) | [My Solution](./problems/problem0374) ||
183184
| 0376 | [Wiggle Subsequence](https://leetcode.com/problems/wiggle-subsequence) | [My Solution](./problems/problem0376) ||
184185
| 0377 | [Combination Sum IV](https://leetcode.com/problems/combination-sum-iv) | [My Solution](./problems/problem0377) ||

0 commit comments

Comments
 (0)