Skip to content

Commit 8f1f1db

Browse files
committed
Merge branch 'master' of https://github.com/halfrost/LeetCode-Go
2 parents 0a614a0 + d27ca9b commit 8f1f1db

File tree

87 files changed

+4698
-1643
lines changed

Some content is hidden

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

87 files changed

+4698
-1643
lines changed

README.md

Lines changed: 905 additions & 890 deletions
Large diffs are not rendered by default.

leetcode/0048.Rotate-Image/README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ Rotate the image by 90 degrees (clockwise).
1010

1111
You have to rotate the image **[in-place](https://en.wikipedia.org/wiki/In-place_algorithm)**, which means you have to modify the input 2D matrix directly. **DO NOT** allocate another 2D matrix and do the rotation.
1212

13-
**Example 1:**
13+
**Example 1**:
1414

15+
![](https://assets.leetcode.com/uploads/2020/08/28/mat1.jpg)
1516

1617
Given input matrix =
1718
[
@@ -28,8 +29,9 @@ You have to rotate the image **[in-place](https://en.wikipedia.org/wiki/In-plac
2829
]
2930

3031

31-
**Example 2:**
32+
**Example 2**:
3233

34+
![](https://assets.leetcode.com/uploads/2020/08/28/mat2.jpg)
3335

3436
Given input matrix =
3537
[

leetcode/0101.Symmetric-Tree/101. Symmetric Tree.go

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,51 @@ type TreeNode = structures.TreeNode
1616
* }
1717
*/
1818

19+
// 解法一 dfs
1920
func isSymmetric(root *TreeNode) bool {
20-
var dfs func(rootLeft, rootRight *TreeNode) bool
21-
dfs = func(rootLeft, rootRight *TreeNode) bool {
22-
if rootLeft == nil && rootRight == nil {
23-
return true
24-
}
25-
if rootLeft == nil || rootRight == nil {
26-
return false
27-
}
28-
if rootLeft.Val != rootRight.Val {
21+
return root == nil || dfs(root.Left, root.Right)
22+
}
23+
24+
func dfs(rootLeft, rootRight *TreeNode) bool {
25+
if rootLeft == nil && rootRight == nil {
26+
return true
27+
}
28+
if rootLeft == nil || rootRight == nil {
29+
return false
30+
}
31+
if rootLeft.Val != rootRight.Val {
32+
return false
33+
}
34+
return dfs(rootLeft.Left, rootRight.Right) && dfs(rootLeft.Right, rootRight.Left)
35+
}
36+
37+
// 解法二
38+
func isSymmetric1(root *TreeNode) bool {
39+
if root == nil {
40+
return true
41+
}
42+
return isSameTree(invertTree(root.Left), root.Right)
43+
}
44+
45+
func isSameTree(p *TreeNode, q *TreeNode) bool {
46+
if p == nil && q == nil {
47+
return true
48+
} else if p != nil && q != nil {
49+
if p.Val != q.Val {
2950
return false
3051
}
31-
return dfs(rootLeft.Left, rootRight.Right) && dfs(rootLeft.Right, rootRight.Left)
52+
return isSameTree(p.Left, q.Left) && isSameTree(p.Right, q.Right)
53+
} else {
54+
return false
3255
}
33-
return root == nil || dfs(root.Left, root.Right)
56+
}
57+
58+
func invertTree(root *TreeNode) *TreeNode {
59+
if root == nil {
60+
return nil
61+
}
62+
invertTree(root.Left)
63+
invertTree(root.Right)
64+
root.Left, root.Right = root.Right, root.Left
65+
return root
3466
}

leetcode/0218.The-Skyline-Problem/218. The Skyline Problem.go

Lines changed: 78 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,83 @@ import (
66
"github.com/halfrost/LeetCode-Go/template"
77
)
88

9-
// 解法一 线段树 Segment Tree,时间复杂度 O(n log n)
9+
// 解法一 树状数组,时间复杂度 O(n log n)
10+
const LEFTSIDE = 1
11+
const RIGHTSIDE = 2
12+
13+
type Point struct {
14+
xAxis int
15+
side int
16+
index int
17+
}
18+
1019
func getSkyline(buildings [][]int) [][]int {
20+
res := [][]int{}
21+
if len(buildings) == 0 {
22+
return res
23+
}
24+
allPoints, bit := make([]Point, 0), BinaryIndexedTree{}
25+
// [x-axis (value), [1 (left) | 2 (right)], index (building number)]
26+
for i, b := range buildings {
27+
allPoints = append(allPoints, Point{xAxis: b[0], side: LEFTSIDE, index: i})
28+
allPoints = append(allPoints, Point{xAxis: b[1], side: RIGHTSIDE, index: i})
29+
}
30+
sort.Slice(allPoints, func(i, j int) bool {
31+
if allPoints[i].xAxis == allPoints[j].xAxis {
32+
return allPoints[i].side < allPoints[j].side
33+
}
34+
return allPoints[i].xAxis < allPoints[j].xAxis
35+
})
36+
bit.Init(len(allPoints))
37+
kth := make(map[Point]int)
38+
for i := 0; i < len(allPoints); i++ {
39+
kth[allPoints[i]] = i
40+
}
41+
for i := 0; i < len(allPoints); i++ {
42+
pt := allPoints[i]
43+
if pt.side == LEFTSIDE {
44+
bit.Add(kth[Point{xAxis: buildings[pt.index][1], side: RIGHTSIDE, index: pt.index}], buildings[pt.index][2])
45+
}
46+
currHeight := bit.Query(kth[pt] + 1)
47+
if len(res) == 0 || res[len(res)-1][1] != currHeight {
48+
if len(res) > 0 && res[len(res)-1][0] == pt.xAxis {
49+
res[len(res)-1][1] = currHeight
50+
} else {
51+
res = append(res, []int{pt.xAxis, currHeight})
52+
}
53+
}
54+
}
55+
return res
56+
}
57+
58+
type BinaryIndexedTree struct {
59+
tree []int
60+
capacity int
61+
}
62+
63+
// Init define
64+
func (bit *BinaryIndexedTree) Init(capacity int) {
65+
bit.tree, bit.capacity = make([]int, capacity+1), capacity
66+
}
67+
68+
// Add define
69+
func (bit *BinaryIndexedTree) Add(index int, val int) {
70+
for ; index > 0; index -= index & -index {
71+
bit.tree[index] = max(bit.tree[index], val)
72+
}
73+
}
74+
75+
// Query define
76+
func (bit *BinaryIndexedTree) Query(index int) int {
77+
sum := 0
78+
for ; index <= bit.capacity; index += index & -index {
79+
sum = max(sum, bit.tree[index])
80+
}
81+
return sum
82+
}
83+
84+
// 解法三 线段树 Segment Tree,时间复杂度 O(n log n)
85+
func getSkyline1(buildings [][]int) [][]int {
1186
st, ans, lastHeight, check := template.SegmentTree{}, [][]int{}, 0, false
1287
posMap, pos := discretization218(buildings)
1388
tmp := make([]int, len(posMap))
@@ -54,8 +129,8 @@ func max(a int, b int) int {
54129
return b
55130
}
56131

57-
// 解法二 扫描线 Sweep Line,时间复杂度 O(n log n)
58-
func getSkyline1(buildings [][]int) [][]int {
132+
// 解法三 扫描线 Sweep Line,时间复杂度 O(n log n)
133+
func getSkyline2(buildings [][]int) [][]int {
59134
size := len(buildings)
60135
es := make([]E, 0)
61136
for i, b := range buildings {

leetcode/0218.The-Skyline-Problem/218. The Skyline Problem_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,16 @@ func Test_Problem218(t *testing.T) {
3030
para218{[][]int{{2, 9, 10}, {3, 7, 15}, {5, 12, 12}, {15, 20, 10}, {19, 24, 8}}},
3131
ans218{[][]int{{2, 10}, {3, 15}, {7, 12}, {12, 0}, {15, 10}, {20, 8}, {24, 0}}},
3232
},
33+
34+
{
35+
para218{[][]int{{1, 2, 1}, {1, 2, 2}, {1, 2, 3}, {2, 3, 1}, {2, 3, 2}, {2, 3, 3}}},
36+
ans218{[][]int{{1, 3}, {3, 0}}},
37+
},
38+
39+
{
40+
para218{[][]int{{4, 9, 10}, {4, 9, 15}, {4, 9, 12}, {10, 12, 10}, {10, 12, 8}}},
41+
ans218{[][]int{{4, 15}, {9, 0}, {10, 10}, {12, 0}}},
42+
},
3343
}
3444

3545
fmt.Printf("------------------------Leetcode Problem 218------------------------\n")

leetcode/0307.Range-Sum-Query---Mutable/307. Range Sum Query - Mutable.go

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package leetcode
22

3-
import (
4-
"github.com/halfrost/LeetCode-Go/template"
5-
)
3+
import "github.com/halfrost/LeetCode-Go/template"
64

75
// NumArray define
86
type NumArray struct {
@@ -23,6 +21,11 @@ func (this *NumArray) Update(i int, val int) {
2321
this.st.Update(i, val)
2422
}
2523

24+
// SumRange define
25+
func (this *NumArray) SumRange(i int, j int) int {
26+
return this.st.Query(i, j)
27+
}
28+
2629
//解法二 prefixSum,sumRange 时间复杂度 O(1)
2730

2831
// // NumArray define
@@ -60,6 +63,30 @@ func (this *NumArray) Update(i int, val int) {
6063
// return this.prefixSum[j]
6164
// }
6265

66+
// 解法三 树状数组
67+
// type NumArray struct {
68+
// bit template.BinaryIndexedTree
69+
// data []int
70+
// }
71+
72+
// // Constructor define
73+
// func Constructor307(nums []int) NumArray {
74+
// bit := template.BinaryIndexedTree{}
75+
// bit.InitWithNums(nums)
76+
// return NumArray{bit: bit, data: nums}
77+
// }
78+
79+
// // Update define
80+
// func (this *NumArray) Update(i int, val int) {
81+
// this.bit.Add(i+1, val-this.data[i])
82+
// this.data[i] = val
83+
// }
84+
85+
// // SumRange define
86+
// func (this *NumArray) SumRange(i int, j int) int {
87+
// return this.bit.Query(j+1) - this.bit.Query(i)
88+
// }
89+
6390
/**
6491
* Your NumArray object will be instantiated and called as such:
6592
* obj := Constructor(nums);

leetcode/0307.Range-Sum-Query---Mutable/307. Range Sum Query - Mutable_test.go

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,25 @@ func Test_Problem307(t *testing.T) {
1212
obj.Update(1, 2)
1313
fmt.Printf("obj = %v\n", obj)
1414
fmt.Printf("SumRange(0,2) = %v\n", obj.SumRange(0, 2))
15-
}
1615

17-
// SumRange define
18-
func (ma *NumArray) SumRange(i int, j int) int {
19-
return ma.st.Query(i, j)
16+
obj = Constructor307([]int{-1})
17+
fmt.Printf("obj = %v\n", obj)
18+
fmt.Printf("SumRange(0,2) = %v\n", obj.SumRange(0, 0))
19+
obj.Update(0, 1)
20+
fmt.Printf("obj = %v\n", obj)
21+
fmt.Printf("SumRange(0,2) = %v\n", obj.SumRange(0, 0))
22+
23+
obj = Constructor307([]int{7, 2, 7, 2, 0})
24+
fmt.Printf("obj = %v\n", obj)
25+
obj.Update(4, 6)
26+
obj.Update(0, 2)
27+
obj.Update(0, 9)
28+
fmt.Printf("SumRange(0,2) = %v\n", obj.SumRange(4, 4))
29+
obj.Update(3, 8)
30+
fmt.Printf("obj = %v\n", obj)
31+
fmt.Printf("SumRange(0,2) = %v\n", obj.SumRange(0, 4))
32+
obj.Update(4, 1)
33+
fmt.Printf("SumRange(0,2) = %v\n", obj.SumRange(0, 3))
34+
fmt.Printf("SumRange(0,2) = %v\n", obj.SumRange(0, 4))
35+
obj.Update(0, 4)
2036
}

leetcode/0307.Range-Sum-Query---Mutable/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,4 @@ sumRange(0, 2) -> 8
4848
- 给出一个数组,数组里面的数都是`**可变**`的,设计一个数据结构能够满足查询数组任意区间内元素的和。
4949
- 对比第 303 题,这一题由于数组里面的元素都是**`可变`**的,所以第一个想到的解法就是线段树,构建一颗线段树,父结点内存的是两个子结点的和,初始化建树的时间复杂度是 O(log n),查询区间元素和的时间复杂度是 O(log n),更新元素值的时间复杂度是 O(log n)。
5050
- 如果此题还用 prefixSum 的思路解答呢?那每次 update 操作的时间复杂度都是 O(n),因为每次更改一个值,最坏情况就是所有的 prefixSum 都要更新一次。prefixSum 的方法在这道题上面也可以 AC,只不过时间排名在 5%,非常差。
51+
- 此题也可以用树状数组解决。代码很直白,区间查询即是两个区间前缀和相减。最简单的树状数组应用。

leetcode/0315.Count-of-Smaller-Numbers-After-Self/315. Count of Smaller Numbers After Self.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"github.com/halfrost/LeetCode-Go/template"
77
)
88

9+
// 解法一 线段树
910
func countSmaller(nums []int) []int {
1011
if len(nums) == 0 {
1112
return []int{}
@@ -35,3 +36,31 @@ func countSmaller(nums []int) []int {
3536
}
3637
return res
3738
}
39+
40+
// 解法二 树状数组
41+
func countSmaller1(nums []int) []int {
42+
// copy 一份原数组至所有数字 allNums 数组中
43+
allNums, res := make([]int, len(nums)), []int{}
44+
copy(allNums, nums)
45+
// 将 allNums 离散化
46+
sort.Ints(allNums)
47+
k := 1
48+
kth := map[int]int{allNums[0]: k}
49+
for i := 1; i < len(allNums); i++ {
50+
if allNums[i] != allNums[i-1] {
51+
k++
52+
kth[allNums[i]] = k
53+
}
54+
}
55+
// 树状数组 Query
56+
bit := template.BinaryIndexedTree{}
57+
bit.Init(k)
58+
for i := len(nums) - 1; i >= 0; i-- {
59+
res = append(res, bit.Query(kth[nums[i]]-1))
60+
bit.Add(kth[nums[i]], 1)
61+
}
62+
for i := 0; i < len(res)/2; i++ {
63+
res[i], res[len(res)-1-i] = res[len(res)-1-i], res[i]
64+
}
65+
return res
66+
}

leetcode/0315.Count-of-Smaller-Numbers-After-Self/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,4 @@ You are given an integer array nums and you have to return a new counts arra
3939

4040
- 给出一个数组,要求输出数组中每个元素相对于数组中的位置右边比它小的元素。
4141
- 这一题是第 327 题的缩水版。由于需要找数组位置右边比当前位置元素小的元素,所以从数组右边开始往左边扫。构造一颗线段树,线段树里面父节点存的是子节点出现的次数和。有可能给的数据会很大,所以构造线段树的时候先离散化。还需要注意的是数组里面可能有重复元素,所以构造线段树要先去重并排序。从右往左扫的过程中,依次添加数组中的元素,添加了一次就立即 query 一次。query 的区间是 [minNum, nums[i]-1]。如果是 minNum 则输出 0,并且也要记得插入这个最小值。这一题的思路和第 327 题大体类似,详解可见第 327 题。
42+
- 这一题同样可以用树状数组来解答。相比 327 题简单很多。第一步还是把所有用到的元素放入 allNums 数组中,第二步排序 + 离散化。由于题目要求输出右侧更小的元素,所以第三步倒序插入构造树状数组,Query 查询 `[1,i-1]` 区间内元素总数即为右侧更小元素个数。注意最终输出是顺序输出,计算是逆序计算的,最终数组里面的答案还需要逆序一遍。相同的套路题有,第 327 题,第 493 题。

0 commit comments

Comments
 (0)