Skip to content

Commit 5521403

Browse files
committed
🎨 [BREAKING] feat: rewrite '@algorithm.ts/sliding-window'
1 parent 949a6c7 commit 5521403

File tree

6 files changed

+117
-90
lines changed

6 files changed

+117
-90
lines changed

Diff for: _fixtures/leetcode/sliding-window-maximum/data.json

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
[
2+
{
3+
"input": [[1, 3, -1, -3, 5, 3, 6, 7], 3],
4+
"answer": [3, 3, 5, 5, 6, 7]
5+
},
6+
{
7+
"input": [[1], 1],
8+
"answer": [1]
9+
},
10+
{
11+
"input": [[1, -1], 1],
12+
"answer": [1, -1]
13+
},
14+
{
15+
"input": [[9, 11], 2],
16+
"answer": [11]
17+
},
18+
{
19+
"input": [[4, -2], 2],
20+
"answer": [4]
21+
}
22+
]

Diff for: packages/sliding-window/README.md

+14-18
Original file line numberDiff line numberDiff line change
@@ -78,27 +78,24 @@ A typescript implementation of the **sliding-window** algorithm.
7878

7979
* `SlidingWindow`
8080

81-
Member | Return | Description
82-
:----------------------------:|:---------:|:---------------------------------------
83-
`init(WINDOW_SIZE?: number)` | `void` | Initialize a sliding window.
84-
`push(idx: number)` | `void` | See a new element with index `idx`.
85-
`max()` | `number` | Get the index of the maximum value in the sliding window.
81+
Member | Return | Description
82+
:----------------------------------------------:|:---------:|:---------------------------------------
83+
`init(WINDOW_SIZE: number, startIdx?: number)` | `void` | Initialize a sliding window.
84+
`moveForward(steps: number)` | `void` | Move the sliding window forward with specified steps.
85+
`max()` | `number` | Get the index of the maximum value in the sliding window.
8686

8787
* `createSlidingWindow`
8888

8989
```typescript
90-
export function createSlidingWindow(
91-
_WINDOW_SIZE: number,
92-
cmp: (x: number, y: number) => -1 | 0 | 1 | number,
93-
): SlidingWindow
90+
export function createSlidingWindow(cmp: (x: number, y: number) => -1 | 0 | 1 | number): ISlidingWindow
9491
```
9592

96-
- `createSlidingWindow(5, (x, y) => nums[x] - nums[y])`:
97-
Create a sliding window with a fixed width of 5, and maintain the index of
93+
- `createSlidingWindow((x, y) => nums[x] - nums[y])`:
94+
Create a sliding window (the window size is not specified yet), and maintain the index of
9895
the nums with the largest value in the window.
9996

100-
- The `slidingWindow.max(10, (x, y) => nums[y] - nums[x])`:
101-
Create a sliding window with a fixed width of 10, and maintain the index of
97+
- The `createSlidingWindow((x, y) => nums[y] - nums[x])`:
98+
Create a sliding window (the window size is not specified yet), and maintain the index of
10299
the nums with the smallest value in the window.
103100

104101

@@ -114,13 +111,12 @@ A typescript implementation of the **sliding-window** algorithm.
114111
if (N < K) return []
115112
116113
const results: number[] = []
117-
const window = createSlidingWindow(K, (x, y) => nums[x] - nums[y])
118-
window.init()
119-
120-
for (let i = 0, _end = K - 1; i < _end; ++i) window.push(i)
114+
const window = createSlidingWindow((x, y) => nums[x] - nums[y])
115+
window.init(K)
121116
117+
window.moveForward(K - 1)
122118
for (let i = K - 1; i < N; ++i) {
123-
window.push(i)
119+
window.moveForward()
124120
results.push(nums[window.max()])
125121
}
126122
return results

Diff for: packages/sliding-window/__test__/leetcode.sliding-window-maximum.spec.ts

-53
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { createSlidingWindow } from '../../src'
2+
3+
export default maxSlidingWindow
4+
5+
export function maxSlidingWindow(nums: number[], K: number): number[] {
6+
const N = nums.length
7+
if (N < K) return []
8+
9+
const results: number[] = []
10+
const window = createSlidingWindow((x, y) => nums[x] - nums[y])
11+
window.init(K)
12+
13+
window.moveForward(K - 1)
14+
for (let i = K - 1; i < N; ++i) {
15+
window.moveForward()
16+
results.push(nums[window.max()])
17+
}
18+
return results
19+
}
+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { testOjCodes } from 'jest.setup'
2+
import { createSlidingWindow } from '../src'
3+
4+
describe('basic', function () {
5+
test('simple', function () {
6+
const elements: number[] = [1, 9, 3, 5, 4, 7, 6, 8, 2]
7+
const f = (idx: number): number => elements[idx]
8+
9+
const slidingWindow = createSlidingWindow((idx: number, idy: number) => f(idx) - f(idy))
10+
slidingWindow.init(3)
11+
12+
slidingWindow.moveForward()
13+
expect(f(slidingWindow.max())).toEqual(1)
14+
15+
slidingWindow.moveForward(2)
16+
expect(f(slidingWindow.max())).toEqual(9)
17+
18+
slidingWindow.moveForward()
19+
expect(f(slidingWindow.max())).toEqual(9)
20+
21+
slidingWindow.moveForward()
22+
expect(f(slidingWindow.max())).toEqual(5)
23+
24+
slidingWindow.moveForward()
25+
expect(f(slidingWindow.max())).toEqual(7)
26+
27+
slidingWindow.moveForward()
28+
expect(f(slidingWindow.max())).toEqual(7)
29+
30+
slidingWindow.moveForward()
31+
expect(f(slidingWindow.max())).toEqual(8)
32+
33+
slidingWindow.moveForward()
34+
expect(f(slidingWindow.max())).toEqual(8)
35+
})
36+
})
37+
38+
describe('oj', function () {
39+
// https://leetcode.com/problems/sliding-window-maximum/
40+
testOjCodes('leetcode/sliding-window-maximum', import('./oj/sliding-window-maximum'))
41+
})

Diff for: packages/sliding-window/src/index.ts

+21-19
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,12 @@ export interface ISlidingWindow {
77
* Initialize a sliding window.
88
* @param WINDOW_SIZE
99
*/
10-
init(WINDOW_SIZE?: number): void
10+
init(WINDOW_SIZE: number, startIdx?: number): void
1111

1212
/**
13-
* See a new element with index `idx`.
14-
* @param idx
13+
* Move the sliding window forward with specified steps.
1514
*/
16-
push(idx: number): void
15+
moveForward(steps?: number): void
1716

1817
/**
1918
* Get the index of the maximum value in the sliding window.
@@ -29,32 +28,35 @@ export interface ISlidingWindow {
2928
* @param cmp
3029
*/
3130
export function createSlidingWindow(
32-
_WINDOW_SIZE: number,
3331
cmp: (x: number, y: number) => -1 | 0 | 1 | number,
3432
): ISlidingWindow {
35-
let front = 0
36-
let end = -1
37-
let WINDOW_SIZE: number = _WINDOW_SIZE
33+
let front: number
34+
let end: number
35+
let idx: number
36+
let WINDOW_SIZE: number
3837
const window: number[] = []
39-
return { init, push, max }
38+
return { init, moveForward, max }
4039

41-
function init(_WINDOW_SIZE?: number): void {
42-
if (_WINDOW_SIZE != null) WINDOW_SIZE = _WINDOW_SIZE
40+
function init(_WINDOW_SIZE: number, startIdx = 0): void {
41+
WINDOW_SIZE = Math.max(1, _WINDOW_SIZE)
4342
window.length = 0
4443
front = 0
4544
end = -1
45+
idx = startIdx
4646
}
4747

48-
function push(idx: number): void {
49-
if (front <= end && idx - window[front] >= WINDOW_SIZE) front += 1
48+
function moveForward(steps = 1): void {
49+
for (let i = 0; i < steps; ++i) {
50+
if (front <= end && idx - window[front] >= WINDOW_SIZE) front += 1
5051

51-
for (; front <= end; end -= 1) {
52-
const delta: number = cmp(window[end], idx)
53-
if (delta > 0) break
54-
}
52+
for (; front <= end; end -= 1) {
53+
const delta: number = cmp(window[end], idx)
54+
if (delta > 0) break
55+
}
5556

56-
// eslint-disable-next-line no-plusplus
57-
window[++end] = idx
57+
// eslint-disable-next-line no-plusplus
58+
window[++end] = idx++
59+
}
5860
}
5961

6062
function max(): number {

0 commit comments

Comments
 (0)