Skip to content

Commit 6ad2df7

Browse files
committed
Merge k Sorted Lists
1 parent 7f347ba commit 6ad2df7

File tree

2 files changed

+219
-0
lines changed

2 files changed

+219
-0
lines changed

23.merge_k_sorted_lists/merge.go

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
// 23. Merge k Sorted Lists
2+
// Topics: 'Linked List', 'Divide and Conquer', 'Heap (Priority Queue)', 'Merge Sort'
3+
// Level: 'Hard'
4+
5+
// You are given an array of k linked-lists lists, each linked-list is sorted in ascending order.
6+
7+
// Merge all the linked-lists into one sorted linked-list and return it.
8+
9+
// Example 1:
10+
11+
// Input: lists = [[1,4,5],[1,3,4],[2,6]]
12+
// Output: [1,1,2,3,4,4,5,6]
13+
// Explanation: The linked-lists are:
14+
// [
15+
// 1->4->5,
16+
// 1->3->4,
17+
// 2->6
18+
// ]
19+
// merging them into one sorted linked list:
20+
// 1->1->2->3->4->4->5->6
21+
22+
// Example 2:
23+
24+
// Input: lists = []
25+
// Output: []
26+
27+
// Example 3:
28+
29+
// Input: lists = [[]]
30+
// Output: []
31+
32+
// Constraints:
33+
34+
// k == lists.length
35+
// 0 <= k <= 104
36+
// 0 <= lists[i].length <= 500
37+
// -104 <= lists[i][j] <= 104
38+
// lists[i] is sorted in ascending order.
39+
// The sum of lists[i].length will not exceed 104.
40+
41+
package mergeksortedlists
42+
43+
func mergeKLists(lists []*ListNode) *ListNode {
44+
if len(lists) < 1 {
45+
return nil
46+
}
47+
if len(lists) == 1 {
48+
return lists[0]
49+
}
50+
51+
return mergeRange(lists, 0, len(lists)-1)
52+
}
53+
54+
func mergeRange(lists []*ListNode, L, R int) *ListNode {
55+
if L == R {
56+
return lists[L]
57+
}
58+
mid := (L + R) / 2
59+
left := mergeRange(lists, L, mid)
60+
right := mergeRange(lists, mid+1, R)
61+
return merge(left, right)
62+
}
63+
64+
func merge(list1, list2 *ListNode) *ListNode {
65+
dummy := &ListNode{}
66+
67+
cur := dummy
68+
cur1 := list1
69+
cur2 := list2
70+
for cur1 != nil && cur2 != nil {
71+
if cur1.Val < cur2.Val {
72+
cur.Next = cur1
73+
cur1 = cur1.Next
74+
} else {
75+
cur.Next = cur2
76+
cur2 = cur2.Next
77+
}
78+
cur = cur.Next
79+
}
80+
81+
if cur1 != nil {
82+
cur.Next = cur1
83+
} else if cur2 != nil {
84+
cur.Next = cur2
85+
}
86+
return dummy.Next
87+
}
88+
89+
type ListNode struct {
90+
Next *ListNode
91+
Val int
92+
}
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
package mergeksortedlists
2+
3+
import (
4+
"reflect"
5+
"testing"
6+
)
7+
8+
func buildList(nums []int) *ListNode {
9+
if len(nums) == 0 {
10+
return nil
11+
}
12+
head := &ListNode{Val: nums[0]}
13+
cur := head
14+
for _, v := range nums[1:] {
15+
cur.Next = &ListNode{Val: v}
16+
cur = cur.Next
17+
}
18+
return head
19+
}
20+
21+
func listToSlice(head *ListNode) []int {
22+
var res []int
23+
for head != nil {
24+
res = append(res, head.Val)
25+
head = head.Next
26+
}
27+
return res
28+
}
29+
30+
func TestMergeKLists(t *testing.T) {
31+
tests := []struct {
32+
name string
33+
input [][]int
34+
expect []int
35+
}{
36+
{
37+
name: "example1",
38+
input: [][]int{{1, 4, 5}, {1, 3, 4}, {2, 6}},
39+
expect: []int{1, 1, 2, 3, 4, 4, 5, 6},
40+
},
41+
{
42+
name: "single list",
43+
input: [][]int{{1, 2, 3}},
44+
expect: []int{1, 2, 3},
45+
},
46+
{
47+
name: "lists with duplicates",
48+
input: [][]int{{1, 1, 2}, {1, 3}, {2, 2}},
49+
expect: []int{1, 1, 1, 2, 2, 2, 3},
50+
},
51+
{
52+
name: "different lengths",
53+
input: [][]int{{1}, {2, 3, 4}, {5, 6}},
54+
expect: []int{1, 2, 3, 4, 5, 6},
55+
},
56+
}
57+
58+
for _, tt := range tests {
59+
t.Run(tt.name, func(t *testing.T) {
60+
var lists []*ListNode
61+
for _, arr := range tt.input {
62+
lists = append(lists, buildList(arr))
63+
}
64+
65+
out := mergeKLists(lists)
66+
got := listToSlice(out)
67+
68+
if !reflect.DeepEqual(got, tt.expect) {
69+
t.Fatalf("expected %v, got %v", tt.expect, got)
70+
}
71+
})
72+
}
73+
}
74+
75+
func TestMerge(t *testing.T) {
76+
tests := []struct {
77+
name string
78+
list1 []int
79+
list2 []int
80+
expect []int
81+
}{
82+
{
83+
name: "both non-empty",
84+
list1: []int{1, 3, 5},
85+
list2: []int{2, 4, 6},
86+
expect: []int{1, 2, 3, 4, 5, 6},
87+
},
88+
{
89+
name: "first list empty",
90+
list1: []int{},
91+
list2: []int{1, 2, 3},
92+
expect: []int{1, 2, 3},
93+
},
94+
{
95+
name: "second list empty",
96+
list1: []int{1, 2, 3},
97+
list2: []int{},
98+
expect: []int{1, 2, 3},
99+
},
100+
{
101+
name: "lists with duplicates",
102+
list1: []int{1, 2, 2},
103+
list2: []int{1, 2, 3},
104+
expect: []int{1, 1, 2, 2, 2, 3},
105+
},
106+
{
107+
name: "different lengths",
108+
list1: []int{1, 4, 7, 10},
109+
list2: []int{2, 3},
110+
expect: []int{1, 2, 3, 4, 7, 10},
111+
},
112+
}
113+
114+
for _, tt := range tests {
115+
t.Run(tt.name, func(t *testing.T) {
116+
l1 := buildList(tt.list1)
117+
l2 := buildList(tt.list2)
118+
119+
out := merge(l1, l2)
120+
got := listToSlice(out)
121+
122+
if !reflect.DeepEqual(got, tt.expect) {
123+
t.Fatalf("expected: %v, got: %v", tt.expect, got)
124+
}
125+
})
126+
}
127+
}

0 commit comments

Comments
 (0)