Skip to content

Commit ec60dbc

Browse files
authored
Merge pull request #41 from mlkr/master
239 两个更快的解法 O(n)
2 parents ea430d1 + a3009ef commit ec60dbc

File tree

2 files changed

+84
-17
lines changed

2 files changed

+84
-17
lines changed
Lines changed: 66 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,78 @@
11
package problem0239
22

33
func maxSlidingWindow(nums []int, k int) []int {
4-
// 题目里面说好了 1 <= k 的
5-
// testcase 里面还是出现了 k == 0
6-
if k == 0 {
7-
return nil
8-
}
4+
res := make([]int, 0, len(nums)-k+1)
5+
window := make([]int, 0, k)
6+
for i, v := range nums {
7+
// 控制 window 窗口大小
8+
if i > k-1 && window[0] == i-k {
9+
window = window[1:]
10+
}
911

10-
// res 的长度是可计算的
11-
res := make([]int, len(nums)-k+1)
12-
for i := 0; i+k <= len(nums); i++ {
13-
res[i] = maxOf(nums[i : i+k])
12+
// window 保持递减
13+
j := len(window) - 1
14+
for ; j >= 0; j-- {
15+
if nums[window[j]] > v {
16+
break
17+
}
18+
}
19+
window = window[:j+1]
20+
window = append(window, i)
21+
22+
// 获取 window 最大值
23+
if i >= k-1 {
24+
res = append(res, nums[window[0]])
25+
}
1426
}
1527

1628
return res
1729
}
1830

19-
// 获取局部的最大值
20-
func maxOf(nums []int) int {
21-
max := nums[0]
22-
for i := 1; i < len(nums); i++ {
23-
if max < nums[i] {
24-
max = nums[i]
31+
// 解法二
32+
// 参看 https://leetcode.com/problems/sliding-window-maximum/discuss/65881/O(n)-solution-in-Java-with-two-simple-pass-in-the-array
33+
// 例子
34+
// nums 1 3 3 -3 5 5 6 7
35+
// k = 3
36+
// left 1 3 3 | -3 5 5 | 6 7
37+
// right 3 3 -1| 5 5 3 | 7 7
38+
// res 3 3 5 5 6 7
39+
func maxSlidingWindow2(nums []int, k int) []int {
40+
size := len(nums)
41+
if size <= 1 {
42+
return nums
43+
}
44+
45+
left, right := make([]int, size), make([]int, size)
46+
left[0], right[size-1] = nums[0], nums[size-1]
47+
48+
for i := 1; i < size; i++ {
49+
if i%k == 0 {
50+
left[i] = nums[i]
51+
} else {
52+
left[i] = max(nums[i], left[i-1])
53+
}
54+
55+
j := size - 1 - i
56+
if (j+1)%k == 0 {
57+
right[j] = nums[j]
58+
} else {
59+
right[j] = max(nums[j], right[j+1])
2560
}
2661
}
27-
return max
62+
63+
res := make([]int, size-k+1)
64+
for i := 0; i <= size-k; i++ {
65+
res[i] = max(right[i], left[i+k-1])
66+
}
67+
68+
return res
69+
70+
}
71+
72+
func max(a, b int) int {
73+
if a > b {
74+
return a
75+
}
76+
77+
return b
2878
}

Algorithms/0239.sliding-window-maximum/sliding-window-maximum_test.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ var tcs = []struct {
1717
{
1818
[]int{},
1919
0,
20-
nil,
20+
[]int{},
2121
},
2222

2323
{
@@ -38,10 +38,27 @@ func Test_maxSlidingWindow(t *testing.T) {
3838
}
3939
}
4040

41+
func Test_maxSlidingWindow2(t *testing.T) {
42+
ast := assert.New(t)
43+
44+
for _, tc := range tcs {
45+
fmt.Printf("~~%v~~\n", tc)
46+
ast.Equal(tc.ans, maxSlidingWindow2(tc.nums, tc.k), "输入:%v", tc)
47+
}
48+
}
49+
4150
func Benchmark_maxSlidingWindow(b *testing.B) {
4251
for i := 0; i < b.N; i++ {
4352
for _, tc := range tcs {
4453
maxSlidingWindow(tc.nums, tc.k)
4554
}
4655
}
4756
}
57+
58+
func Benchmark_maxSlidingWindow2(b *testing.B) {
59+
for i := 0; i < b.N; i++ {
60+
for _, tc := range tcs {
61+
maxSlidingWindow2(tc.nums, tc.k)
62+
}
63+
}
64+
}

0 commit comments

Comments
 (0)