Skip to content

Commit 6f5d78d

Browse files
author
semantic-release
committed
10.6.0
Automatically generated by python-semantic-release
1 parent 03d4c95 commit 6f5d78d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+5450
-1703
lines changed

README.md

Lines changed: 54 additions & 1703 deletions
Large diffs are not rendered by default.

array/binary_search.md

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# 二分查找
2+
3+
**「二分」的本质是二段性,并非单调性。只要一段满足某个性质,另外一段不满足某个性质,就可以用「二分」。**
4+
5+
```python3
6+
# bisect.bisect_left
7+
def binary_search(arr, target):
8+
left, right = 0, len(arr) - 1
9+
while left <= right:
10+
mid = left + (right - left) // 2
11+
if arr[mid] == target:
12+
return mid
13+
elif arr[mid] < target:
14+
left = mid + 1
15+
else:
16+
right = mid - 1
17+
return -1
18+
```
19+
20+
```go
21+
package main
22+
23+
func BinarySearch(arr []int, target int) int {
24+
left, right := 0, len(arr)-1
25+
for left <= right {
26+
mid := left + (right-left)/2
27+
if arr[mid] == target {
28+
return mid
29+
} else if arr[mid] < target {
30+
left = mid + 1
31+
} else {
32+
right = mid - 1
33+
}
34+
}
35+
return -1
36+
}
37+
```
38+
39+
## 带重复元素的旋转数组
40+
41+
```go
42+
package main
43+
44+
// 这里的二段性是一段满足<target,另一段不满足
45+
func binarySearch(nums []int, left, right, target int) int {
46+
l, r := left, right
47+
for l < r {
48+
mid := l + (r-l)/2
49+
if nums[mid] < target {
50+
l = mid + 1
51+
} else {
52+
r = mid
53+
}
54+
}
55+
if nums[r] == target {
56+
return r
57+
}
58+
return -1
59+
}
60+
61+
func search(nums []int, target int) bool {
62+
n := len(nums)
63+
left, right := 0, n-1
64+
// 恢复二段性
65+
for left < right && nums[right] == nums[left] {
66+
right--
67+
}
68+
// 这里的二段性是一段满足>=nums[0],另一段不满足
69+
for left < right {
70+
mid := left + (right-left+1)/2
71+
if nums[mid] >= nums[0] {
72+
left = mid
73+
} else {
74+
right = mid - 1
75+
}
76+
}
77+
idx := n
78+
if nums[right] >= nums[0] && right < n-1 {
79+
idx = right + 1
80+
}
81+
if target >= nums[0] {
82+
return binarySearch(nums, 0, idx-1, target) != -1
83+
} else {
84+
return binarySearch(nums, idx, n-1, target) != -1
85+
}
86+
}
87+
```

array/differential.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# 差分数组
2+

array/double_pointer.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# 双指针
2+
3+
- 双指针技巧通常用于处理数组或链表问题,如**快慢指针**检测循环、**左右指针**解决有序数组问题等。
4+
5+
## 示例:移除元素(原地删除)
6+
7+
```python
8+
def remove_element(nums, val):
9+
slow = 0
10+
for fast in range(len(nums)):
11+
if nums[fast] != val:
12+
nums[slow] = nums[fast]
13+
slow += 1
14+
return slow
15+
```
16+
17+
```go
18+
package main
19+
20+
func removeElement(nums []int, val int) int {
21+
slow := 0
22+
for fast := 0; fast < len(nums); fast++ {
23+
if nums[fast] != val {
24+
nums[slow] = nums[fast]
25+
slow++
26+
}
27+
}
28+
return slow
29+
}
30+
```
31+
32+
## 示例:有序数组两数之和
33+
34+
```python
35+
def two_sum(nums, target):
36+
left, right = 0, len(nums) - 1
37+
while left < right:
38+
s = nums[left] + nums[right]
39+
if s == target:
40+
return [left + 1, right + 1]
41+
elif s < target:
42+
left += 1
43+
else:
44+
right -= 1
45+
return []
46+
```
47+
48+
```go
49+
package main
50+
51+
func twoSum(nums []int, target int) []int {
52+
left, right := 0, len(nums)-1
53+
for left < right {
54+
sum := nums[left] + nums[right]
55+
if sum == target {
56+
return []int{left+1, right+1}
57+
} else if sum < target {
58+
left++
59+
} else {
60+
right--
61+
}
62+
}
63+
return []int{}
64+
}
65+
```

array/monotonic_stack.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# 单调栈
2+
3+
## 单调栈适用场景
4+
5+
单调栈可以在时间复杂度为$`O(n)`$,求解出某个元素左边或者右边第一个比它大或者小的元素。
6+
7+
单调栈一般用于解决一下几种问题:
8+
9+
- 寻找左侧第一个比当前元素大的元素。
10+
- 寻找左侧第一个比当前元素小的元素。
11+
- 寻找右侧第一个比当前元素大的元素。
12+
- 寻找右侧第一个比当前元素小的元素。
13+
14+
```python3
15+
def solve(nums):
16+
max_stack = []
17+
for i, num in enumerate(nums):
18+
while max_stack and num > nums[max_stack[-1]]:
19+
max_stack.pop()
20+
max_stack.append(i)
21+
```
22+
23+
```go
24+
package main
25+
26+
func subArrayRanges(nums []int) (ans int64) {
27+
n := len(nums)
28+
minStack, maxStack := make([]int, 0, n), make([]int, 0, n)
29+
for i := 0; i <= n; i++ {
30+
for len(maxStack) > 0 && (i == n || nums[i] > nums[maxStack[len(maxStack)-1]]) {
31+
j := maxStack[len(maxStack)-1]
32+
maxStack = maxStack[:len(maxStack)-1]
33+
left := -1
34+
if len(maxStack) > 0 {
35+
left = maxStack[len(maxStack)-1]
36+
}
37+
ans += int64(nums[j]) * int64(j-left) * int64(i-j)
38+
}
39+
maxStack = append(maxStack, i)
40+
for len(minStack) > 0 && (i == n || nums[i] < nums[minStack[len(minStack)-1]]) {
41+
j := minStack[len(minStack)-1]
42+
minStack = minStack[:len(minStack)-1]
43+
left := -1
44+
if len(minStack) > 0 {
45+
left = minStack[len(minStack)-1]
46+
}
47+
ans -= int64(nums[j]) * int64(j-left) * int64(i-j)
48+
}
49+
minStack = append(minStack, i)
50+
}
51+
return
52+
}
53+
```

array/prefix_sum.md

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# 前缀和
2+
3+
$`prefix\_sum[i] = \sum_{k=0}^{i-1} nums[k]`$
4+
5+
$`prefix\_sum[i] - prefix\_sum[j] = \sum_{k=j}^{i-1} nums[k]`$
6+
7+
```python
8+
from itertools import accumulate
9+
10+
11+
def pivot_index(nums) -> int:
12+
pre_sum = [0] + list(accumulate(nums))
13+
for i, num in enumerate(nums):
14+
if pre_sum[i] == pre_sum[-1] - pre_sum[i + 1]:
15+
return i
16+
return -1
17+
```
18+
19+
```go
20+
package main
21+
22+
func pivotIndex(nums []int) int {
23+
n := len(nums)
24+
prefixSum := make([]int, n+1)
25+
for i := 0; i < n; i++ {
26+
prefixSum[i+1] = prefixSum[i] + nums[i]
27+
}
28+
for i := 0; i < n; i++ {
29+
if prefixSum[i] == prefixSum[n]-prefixSum[i+1] {
30+
return i
31+
}
32+
}
33+
return -1
34+
}
35+
```
36+
37+
## 二维前缀和
38+
39+
$`prefix\_sum[i][j] = \sum_{k=0}^{i-1} \sum_{l=0}^{j-1} matrix[k][l]`$
40+
41+
$
42+
`prefix\_sum[i][j] - prefix\_sum[i][l] - prefix\_sum[k][j] + prefix\_sum[k][l] = \sum_{x=k}^{i-1} \sum_{y=l}^{j-1} matrix[x][y]`$
43+
44+
```python
45+
def sum_region(matrix, row1, col1, row2, col2):
46+
m = len(matrix)
47+
if m == 0:
48+
return 0
49+
n = len(matrix[0])
50+
pre_sum = [[0] * (n + 1) for _ in range(m + 1)]
51+
for i in range(1, m + 1):
52+
for j in range(1, n + 1):
53+
pre_sum[i][j] = pre_sum[i - 1][j] + pre_sum[i][j - 1] - pre_sum[i - 1][j - 1] + matrix[i - 1][j - 1]
54+
return pre_sum[row2 + 1][col2 + 1] - pre_sum[row1][col2 + 1] - pre_sum[row2 + 1][col1] + pre_sum[row1][col1]
55+
```
56+
57+
```go
58+
package main
59+
60+
type NumMatrix struct {
61+
preSum [][]int
62+
}
63+
64+
func Constructor(matrix [][]int) NumMatrix {
65+
m := len(matrix)
66+
if m == 0 {
67+
return NumMatrix{}
68+
}
69+
n := len(matrix[0])
70+
preSum := make([][]int, m+1)
71+
for i := range preSum {
72+
preSum[i] = make([]int, n+1)
73+
}
74+
75+
for i := 1; i <= m; i++ {
76+
for j := 1; j <= n; j++ {
77+
preSum[i][j] = preSum[i-1][j] + preSum[i][j-1] - preSum[i-1][j-1] + matrix[i-1][j-1]
78+
}
79+
}
80+
return NumMatrix{preSum: preSum}
81+
}
82+
83+
func (this *NumMatrix) SumRegion(row1 int, col1 int, row2 int, col2 int) int {
84+
return this.preSum[row2+1][col2+1] - this.preSum[row1][col2+1] - this.preSum[row2+1][col1] + this.preSum[row1][col1]
85+
}
86+
```

array/sliding_window.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# 滑动窗口
2+
3+
```python3
4+
def max_sliding_window(nums, k):
5+
from collections import deque
6+
q = deque()
7+
res = []
8+
for i in range(len(nums)):
9+
if q and q[0] < i - k + 1:
10+
q.popleft()
11+
while q and nums[q[-1]] < nums[i]:
12+
q.pop()
13+
q.append(i)
14+
if i >= k - 1:
15+
res.append(nums[q[0]])
16+
return res
17+
```
18+
19+
```go
20+
package main
21+
22+
func maxSlidingWindow(nums []int, k int) (ans []int) {
23+
q := make([]int, 0)
24+
for i := range nums {
25+
if len(q) > 0 && q[0] < i-k+1 {
26+
q = q[1:]
27+
}
28+
for len(q) > 0 && nums[q[len(q)-1]] < nums[i] {
29+
q = q[:len(q)-1]
30+
}
31+
q = append(q, i)
32+
if i >= k-1 {
33+
ans = append(ans, nums[q[0]])
34+
}
35+
}
36+
return
37+
}
38+
```

0 commit comments

Comments
 (0)