mirror of
https://github.com/halfrost/LeetCode-Go.git
synced 2025-07-07 01:44:56 +08:00
Compare commits
324 Commits
1.6.6
...
revert-175
Author | SHA1 | Date | |
---|---|---|---|
be6831e5e3 | |||
f09ea6cd09 | |||
7d3ba345f3 | |||
a3f71751eb | |||
2051a1b67c | |||
0a3c4d0ed8 | |||
2608238acb | |||
7d08f48786 | |||
af654b2e51 | |||
796b4b6582 | |||
9effade48f | |||
44541dc0ef | |||
f68bec22d9 | |||
0e69148802 | |||
819145dca6 | |||
4b3ef8a97d | |||
24ee84feaf | |||
d3bb8b6279 | |||
219c53bb03 | |||
16b1ab75bd | |||
325e5130b7 | |||
bde069b75e | |||
f461eadb78 | |||
d32347137a | |||
71b771dc5d | |||
0d3b70571a | |||
bef7599068 | |||
3c11d93a29 | |||
29880358f0 | |||
7db2a76fd6 | |||
5c0f4f9103 | |||
3c85ef6e7a | |||
a2dcc00524 | |||
f793b7aa48 | |||
81d298f55c | |||
07034111d5 | |||
7acf5110db | |||
50f90ec045 | |||
1c71c1f0a5 | |||
eec96cae11 | |||
59c4b30d23 | |||
c551601a99 | |||
086c7c9eda | |||
2e628eb33d | |||
a3f55d9560 | |||
e89003a2e3 | |||
61a586e96a | |||
e6bce61e81 | |||
d1a87f1cbf | |||
5e49c8db0c | |||
daa7c7f044 | |||
d0f54e2bbd | |||
2189396c54 | |||
4268f5837b | |||
a43125dc18 | |||
35530a4de4 | |||
d1e24bf344 | |||
6e74af9d6c | |||
33f616c7dc | |||
c1d27a197b | |||
3de30e7848 | |||
e4505aab14 | |||
78f8879463 | |||
3755d3f251 | |||
ae5c145c3f | |||
07ddc128b4 | |||
674e50ba0d | |||
2f2ba72e92 | |||
0547b8b075 | |||
040ac16526 | |||
1c662f4330 | |||
765bb777e3 | |||
23beddc2b1 | |||
7b7a39291a | |||
21e5e780cc | |||
97928e7abe | |||
28add7d729 | |||
0823979d78 | |||
c7d4051054 | |||
8b41ad38d3 | |||
8c1235bdf1 | |||
dd26b1df3e | |||
02999e422e | |||
82b544c664 | |||
443b7ce63d | |||
eda4953c3d | |||
41b03831b3 | |||
da7f306dcb | |||
c8aa2a477e | |||
f5716a22aa | |||
185b1e1c3b | |||
c39400373d | |||
e04b83ff2c | |||
992ccf0054 | |||
cb6023e722 | |||
4af8e959b6 | |||
04679fe8bc | |||
7a3db717e0 | |||
38ffcbc1af | |||
d5c5284b1a | |||
bc7c912aa9 | |||
dbf56b5db8 | |||
127b852d7d | |||
cfb67acf6d | |||
f663cec583 | |||
e216ed4430 | |||
7c7f09da99 | |||
a616d6ea09 | |||
5e6c9b1fc0 | |||
44431beba4 | |||
1cef508aa3 | |||
21c05df2ba | |||
b11b8bf09c | |||
f94128417a | |||
d1c6d8777a | |||
1198fcc279 | |||
014e437944 | |||
1eb35d880f | |||
c5a9c0fc5c | |||
8ae9b96b33 | |||
871204438b | |||
cb1a2124a7 | |||
820f3ddd28 | |||
873183cc77 | |||
8741a38fe2 | |||
b273c3f088 | |||
578c85e416 | |||
804bf60609 | |||
75b8f85315 | |||
c28e1c0267 | |||
fe99f9d7d5 | |||
eb5eb51233 | |||
4d91e41bef | |||
7a90f3713d | |||
555737bcff | |||
5cf1b806b1 | |||
48cb642554 | |||
fe13c6dc18 | |||
b2a4f39401 | |||
259eba0c84 | |||
aa8912611f | |||
dbdc464dee | |||
640dc700a6 | |||
d0c6f905f6 | |||
295504eb45 | |||
cc78fdd0ef | |||
c0191c235d | |||
60d3b04030 | |||
2104d8f332 | |||
ec597e285d | |||
d61a0226b8 | |||
135754159e | |||
9e357544d1 | |||
3dac8b9e82 | |||
9fb39146b7 | |||
e256d74761 | |||
5cd43244e9 | |||
cff768e63c | |||
ad3dfff270 | |||
7ca6279850 | |||
44eddae9d0 | |||
95eddf7a24 | |||
889e495992 | |||
22e9be3663 | |||
11f3e13688 | |||
315d4fa8d8 | |||
7a3fe1fed2 | |||
00b6d1a6ca | |||
38875b19fb | |||
44c68a333a | |||
6d2d38e124 | |||
851e0eaad5 | |||
d5aacae9d2 | |||
58f6f7fedb | |||
9dbefba7cd | |||
991cb6e3d7 | |||
4330393c9b | |||
cd5572f250 | |||
776fe07932 | |||
36f3a4c757 | |||
86370c1ac5 | |||
bb50f33fec | |||
be276a58dc | |||
0d64196cf1 | |||
5e77733f1a | |||
851946dc9a | |||
e72e4cb599 | |||
40201dceb1 | |||
e3304f5a83 | |||
3c1176be43 | |||
012999a33b | |||
2a164310be | |||
9347140480 | |||
87c5b40454 | |||
9a30c0094e | |||
09c6e478e1 | |||
98c5414092 | |||
76753e8ca6 | |||
a10cebc033 | |||
5f6ea09570 | |||
2a115eccc3 | |||
2450cf4dd0 | |||
1835b6dd45 | |||
24829288bb | |||
624a9ae9e6 | |||
70aafb68d4 | |||
0c817666f5 | |||
99fe55c7df | |||
65f4c4f060 | |||
1071ae0455 | |||
3d5df51382 | |||
4abb13e6ca | |||
9c0603ea84 | |||
dd99c2c7e1 | |||
bff8947a8b | |||
678bc75719 | |||
86856f687a | |||
1eb4bf698a | |||
594af3f4d8 | |||
0f1bb00e62 | |||
01ce0fd9b1 | |||
099e31ea64 | |||
97b5aaf1c2 | |||
87c8048afb | |||
2d5005a24a | |||
263ca6e3b7 | |||
8f1f1db6f2 | |||
0a614a0e79 | |||
d27ca9bd0a | |||
6fcc9ec669 | |||
0a87bb5a02 | |||
f92ac03f8f | |||
4be7d82168 | |||
45fb40ee7f | |||
1cdbefdc9c | |||
fd409dcbd1 | |||
8a14f2c734 | |||
732095c59a | |||
d4d5a20eb1 | |||
e0aed6a035 | |||
19e5c7e9c9 | |||
ebd8951db4 | |||
4e6a1e3287 | |||
370ec68c76 | |||
8ee289c17c | |||
5fbca5f096 | |||
4c59f10469 | |||
18e6d08e93 | |||
784e731c77 | |||
09463eee6f | |||
ec4cc41102 | |||
d3c556bb5d | |||
86fac4e139 | |||
7f0a3b514f | |||
7cbef318e1 | |||
541ec13f70 | |||
8b5785532a | |||
858198e385 | |||
d47c2ec4c3 | |||
8ded561341 | |||
a8f9bfb98c | |||
1376328b0b | |||
dab1f90a2f | |||
ce600d6822 | |||
f376eaf316 | |||
a15f91f029 | |||
a6ee37ebef | |||
eb2331edb6 | |||
c5a6ac4b11 | |||
58dcf6b469 | |||
ce93f89531 | |||
6d37f59f97 | |||
9bd6121476 | |||
99cea18cc6 | |||
d798338426 | |||
3fc7e9c543 | |||
984b06f29c | |||
417635f58c | |||
aa5bccb403 | |||
b4d7a80343 | |||
e10eaa99f8 | |||
427b25d4b7 | |||
1781d4e7a5 | |||
0c519027d4 | |||
fec98dba7f | |||
613fa9aa92 | |||
fe7d9845bd | |||
23a0f0a2b4 | |||
031d96b369 | |||
1cd9cec988 | |||
89af12786a | |||
c92b576018 | |||
096f514b66 | |||
6cbaad13b1 | |||
c30c6c7f41 | |||
943d558ca8 | |||
53e10a59c1 | |||
8bb84f2edc | |||
a841eac968 | |||
1eac64966f | |||
2e7dd977c4 | |||
11e38a651e | |||
21fda4f75f | |||
3f3026ca05 | |||
66e690a277 | |||
87c1060ef5 | |||
ee741232d4 | |||
f0c5270f84 | |||
a7a40da0aa | |||
b4eab90b74 | |||
c839a96874 | |||
cf841b821b | |||
fd62b9f721 | |||
d12dde092f | |||
075d7ba884 | |||
4dc97cd730 | |||
6c7d4fb59a | |||
28b422f87f | |||
8e01a1c176 | |||
2af901862f | |||
5a2331afd4 | |||
be7fe42dcd | |||
86e61e9dc6 | |||
917d613465 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
||||
*.toml
|
||||
.idea
|
||||
|
21
ctl/label.go
21
ctl/label.go
@ -4,20 +4,21 @@ import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/halfrost/LeetCode-Go/ctl/util"
|
||||
"github.com/spf13/cobra"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/halfrost/LeetCode-Go/ctl/util"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
chapterOneFileOrder = []string{"_index", "Data_Structure", "Algorithm"}
|
||||
chapterOneMenuOrder = []string{"_index", "#关于作者", "Data_Structure", "Algorithm"}
|
||||
chapterOneFileOrder = []string{"_index", "Data_Structure", "Algorithm", "Time_Complexity"}
|
||||
chapterOneMenuOrder = []string{"_index", "#关于作者", "Data_Structure", "Algorithm", "Time_Complexity"}
|
||||
chapterTwoFileOrder = []string{"_index", "Array", "String", "Two_Pointers", "Linked_List", "Stack", "Tree", "Dynamic_Programming", "Backtracking", "Depth_First_Search", "Breadth_First_Search",
|
||||
"Binary_Search", "Math", "Hash_Table", "Sort", "Bit_Manipulation", "Union_Find", "Sliding_Window", "Segment_Tree", "Binary_Indexed_Tree"}
|
||||
"Binary_Search", "Math", "Hash_Table", "Sorting", "Bit_Manipulation", "Union_Find", "Sliding_Window", "Segment_Tree", "Binary_Indexed_Tree"}
|
||||
chapterThreeFileOrder = []string{"_index", "Segment_Tree", "UnionFind", "LRUCache", "LFUCache"}
|
||||
preNextHeader = "----------------------------------------------\n<div style=\"display: flex;justify-content: space-between;align-items: center;\">\n"
|
||||
preNextFotter = "</div>"
|
||||
@ -34,10 +35,10 @@ var (
|
||||
|
||||
chapterMap = map[string]map[string]string{
|
||||
"ChapterOne": {
|
||||
"_index": "第一章 序章",
|
||||
"#关于作者": "1.1 关于作者",
|
||||
"Data_Structure": "1.2 数据结构知识",
|
||||
"Algorithm": "1.3 算法知识",
|
||||
"_index": "第一章 序章",
|
||||
"Data_Structure": "1.1 数据结构知识",
|
||||
"Algorithm": "1.2 算法知识",
|
||||
"Time_Complexity": "1.3 时间复杂度",
|
||||
},
|
||||
"ChapterTwo": {
|
||||
"_index": "第二章 算法专题",
|
||||
@ -54,7 +55,7 @@ var (
|
||||
"Binary_Search": "2.11 Binary Search",
|
||||
"Math": "2.12 Math",
|
||||
"Hash_Table": "2.13 Hash Table",
|
||||
"Sort": "2.14 ✅ Sort",
|
||||
"Sorting": "2.14 ✅ Sorting",
|
||||
"Bit_Manipulation": "2.15 ✅ Bit Manipulation",
|
||||
"Union_Find": "2.16 ✅ Union Find",
|
||||
"Sliding_Window": "2.17 ✅ Sliding Window",
|
||||
|
@ -1,7 +1,7 @@
|
||||
|56. Merge Intervals | [Go]({{< relref "/ChapterFour/0056.Merge-Intervals.md" >}})| Medium | O(n log n)| O(log n)||
|
||||
|57. Insert Interval | [Go]({{< relref "/ChapterFour/0057.Insert-Interval.md" >}})| Hard | O(n)| O(1)||
|
||||
|75. Sort Colors | [Go]({{< relref "/ChapterFour/0075.Sort-Colors.md" >}})| Medium| O(n)| O(1)|❤️|
|
||||
|147. Insertion Sort List | [Go]({{< relref "/ChapterFour/0147.Insertion-Sort-List.md" >}})| Medium | O(n)| O(1) |❤️|
|
||||
|147. Insertion Sort List | [Go]({{< relref "/ChapterFour/0147.Insertion-Sort-List.md" >}})| Medium | O(n^2)| O(1) |❤️|
|
||||
|148. Sort List | [Go]({{< relref "/ChapterFour/0148.Sort-List.md" >}})| Medium |O(n log n)| O(log n)|❤️|
|
||||
|164. Maximum Gap | [Go]({{< relref "/ChapterFour/0164.Maximum-Gap.md" >}})| Hard | O(n log n)| O(log n) |❤️|
|
||||
|179. Largest Number | [Go]({{< relref "/ChapterFour/0179.Largest-Number.md" >}})| Medium | O(n log n)| O(log n) |❤️|
|
@ -18,15 +18,38 @@ type Mdrow struct {
|
||||
|
||||
// GenerateMdRows define
|
||||
func GenerateMdRows(solutionIds []int, mdrows []Mdrow) {
|
||||
mdMap := map[int]Mdrow{}
|
||||
for _, row := range mdrows {
|
||||
mdMap[int(row.FrontendQuestionID)] = row
|
||||
}
|
||||
for i := 0; i < len(solutionIds); i++ {
|
||||
id := mdrows[solutionIds[i]-1].FrontendQuestionID
|
||||
if solutionIds[i] == int(id) {
|
||||
//fmt.Printf("id = %v i = %v solutionIds = %v\n", id, i, solutionIds[i])
|
||||
mdrows[id-1].SolutionPath = fmt.Sprintf("[Go](https://github.com/halfrost/LeetCode-Go/tree/master/leetcode/%v)", fmt.Sprintf("%04d.%v", id, strings.Replace(strings.TrimSpace(mdrows[id-1].QuestionTitle), " ", "-", -1)))
|
||||
if row, ok := mdMap[solutionIds[i]]; ok {
|
||||
s7 := standardizedTitle(row.QuestionTitle, row.FrontendQuestionID)
|
||||
mdMap[solutionIds[i]] = Mdrow{
|
||||
FrontendQuestionID: row.FrontendQuestionID,
|
||||
QuestionTitle: strings.TrimSpace(row.QuestionTitle),
|
||||
QuestionTitleSlug: row.QuestionTitleSlug,
|
||||
SolutionPath: fmt.Sprintf("[Go](https://github.com/halfrost/LeetCode-Go/tree/master/leetcode/%v)", fmt.Sprintf("%04d.%v", solutionIds[i], s7)),
|
||||
Acceptance: row.Acceptance,
|
||||
Difficulty: row.Difficulty,
|
||||
Frequency: row.Frequency,
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("序号出错了 solutionIds = %v id = %v\n", solutionIds[i], id)
|
||||
fmt.Printf("序号不存在 len(solutionIds) = %v len(mdrows) = %v len(solutionIds) = %v solutionIds[i] = %v QuestionTitle = %v\n", len(solutionIds), len(mdrows), len(solutionIds), solutionIds[i], mdrows[solutionIds[i]-1].QuestionTitle)
|
||||
}
|
||||
}
|
||||
for i := range mdrows {
|
||||
mdrows[i] = Mdrow{
|
||||
FrontendQuestionID: mdrows[i].FrontendQuestionID,
|
||||
QuestionTitle: strings.TrimSpace(mdrows[i].QuestionTitle),
|
||||
QuestionTitleSlug: mdrows[i].QuestionTitleSlug,
|
||||
SolutionPath: mdMap[int(mdrows[i].FrontendQuestionID)].SolutionPath,
|
||||
Acceptance: mdrows[i].Acceptance,
|
||||
Difficulty: mdrows[i].Difficulty,
|
||||
Frequency: mdrows[i].Frequency,
|
||||
}
|
||||
}
|
||||
// fmt.Printf("mdrows = %v\n\n", mdrows)
|
||||
}
|
||||
|
||||
// | 0001 | Two Sum | [Go](https://github.com/halfrost/LeetCode-Go/tree/master/leetcode/0001.Two-Sum)| 45.6% | Easy | |
|
||||
|
@ -115,6 +115,41 @@ func (t TagList) tableLine() string {
|
||||
return fmt.Sprintf("|%04d|%v|%v|%v|%v|%v|%v|%v|\n", t.FrontendQuestionID, t.QuestionTitle, t.SolutionPath, t.Difficulty, t.TimeComplexity, t.SpaceComplexity, t.Favorite, t.Acceptance)
|
||||
}
|
||||
|
||||
func standardizedTitle(orig string, frontendQuestionID int32) string {
|
||||
s0 := strings.TrimSpace(orig)
|
||||
s1 := strings.Replace(s0, " ", "-", -1)
|
||||
s2 := strings.Replace(s1, "'", "", -1)
|
||||
s3 := strings.Replace(s2, "%", "", -1)
|
||||
s4 := strings.Replace(s3, "(", "", -1)
|
||||
s5 := strings.Replace(s4, ")", "", -1)
|
||||
s6 := strings.Replace(s5, ",", "", -1)
|
||||
s7 := strings.Replace(s6, "?", "", -1)
|
||||
count := 0
|
||||
// 去掉 --- 这种情况,这种情况是由于题目标题中包含 - ,左右有空格,左右一填充,造成了 ---,3 个 -
|
||||
for i := 0; i < len(s7)-2; i++ {
|
||||
if s7[i] == '-' && s7[i+1] == '-' && s7[i+2] == '-' {
|
||||
fmt.Printf("【需要修正 --- 的标题是 %v】\n", fmt.Sprintf("%04d.%v", int(frontendQuestionID), s7))
|
||||
s7 = s7[:i+1] + s7[i+3:]
|
||||
count++
|
||||
}
|
||||
}
|
||||
if count > 0 {
|
||||
fmt.Printf("总共修正了 %v 个标题\n", count)
|
||||
}
|
||||
// 去掉 -- 这种情况,这种情况是由于题目标题中包含负号 -
|
||||
for i := 0; i < len(s7)-2; i++ {
|
||||
if s7[i] == '-' && s7[i+1] == '-' {
|
||||
fmt.Printf("【需要修正 -- 的标题是 %v】\n", fmt.Sprintf("%04d.%v", int(frontendQuestionID), s7))
|
||||
s7 = s7[:i+1] + s7[i+2:]
|
||||
count++
|
||||
}
|
||||
}
|
||||
if count > 0 {
|
||||
fmt.Printf("总共修正了 %v 个标题\n", count)
|
||||
}
|
||||
return s7
|
||||
}
|
||||
|
||||
// GenerateTagMdRows define
|
||||
func GenerateTagMdRows(solutionIds []int, metaMap map[int]TagList, mdrows []Mdrow, internal bool) []TagList {
|
||||
tl := []TagList{}
|
||||
@ -123,13 +158,7 @@ func GenerateTagMdRows(solutionIds []int, metaMap map[int]TagList, mdrows []Mdro
|
||||
tmp := TagList{}
|
||||
tmp.FrontendQuestionID = row.FrontendQuestionID
|
||||
tmp.QuestionTitle = strings.TrimSpace(row.QuestionTitle)
|
||||
s1 := strings.Replace(tmp.QuestionTitle, " ", "-", -1)
|
||||
s2 := strings.Replace(s1, "'", "", -1)
|
||||
s3 := strings.Replace(s2, "%", "", -1)
|
||||
s4 := strings.Replace(s3, "(", "", -1)
|
||||
s5 := strings.Replace(s4, ")", "", -1)
|
||||
s6 := strings.Replace(s5, ",", "", -1)
|
||||
s7 := strings.Replace(s6, "?", "", -1)
|
||||
s7 := standardizedTitle(row.QuestionTitle, row.FrontendQuestionID)
|
||||
if internal {
|
||||
tmp.SolutionPath = fmt.Sprintf("[Go]({{< relref \"/ChapterFour/%v/%v.md\" >}})", util.GetChpaterFourFileNum(int(row.FrontendQuestionID)), fmt.Sprintf("%04d.%v", int(row.FrontendQuestionID), s7))
|
||||
} else {
|
||||
|
@ -18,11 +18,11 @@ import (
|
||||
|
||||
var (
|
||||
chapterTwoList = []string{"Array", "String", "Two Pointers", "Linked List", "Stack", "Tree", "Dynamic Programming", "Backtracking", "Depth First Search", "Breadth First Search",
|
||||
"Binary Search", "Math", "Hash Table", "Sort", "Bit Manipulation", "Union Find", "Sliding Window", "Segment Tree", "Binary Indexed Tree"}
|
||||
"Binary Search", "Math", "Hash Table", "Sorting", "Bit Manipulation", "Union Find", "Sliding Window", "Segment Tree", "Binary Indexed Tree"}
|
||||
chapterTwoFileName = []string{"Array", "String", "Two_Pointers", "Linked_List", "Stack", "Tree", "Dynamic_Programming", "Backtracking", "Depth_First_Search", "Breadth_First_Search",
|
||||
"Binary_Search", "Math", "Hash_Table", "Sort", "Bit_Manipulation", "Union_Find", "Sliding_Window", "Segment_Tree", "Binary_Indexed_Tree"}
|
||||
"Binary_Search", "Math", "Hash_Table", "Sorting", "Bit_Manipulation", "Union_Find", "Sliding_Window", "Segment_Tree", "Binary_Indexed_Tree"}
|
||||
chapterTwoSlug = []string{"array", "string", "two-pointers", "linked-list", "stack", "tree", "dynamic-programming", "backtracking", "depth-first-search", "breadth-first-search",
|
||||
"binary-search", "math", "hash-table", "sort", "bit-manipulation", "union-find", "sliding-window", "segment-tree", "binary-indexed-tree"}
|
||||
"binary-search", "math", "hash-table", "sorting", "bit-manipulation", "union-find", "sliding-window", "segment-tree", "binary-indexed-tree"}
|
||||
)
|
||||
|
||||
func newBuildCommand() *cobra.Command {
|
||||
|
@ -1,10 +1,10 @@
|
||||
---
|
||||
title: 2.14 ✅ Sort
|
||||
title: 2.14 ✅ Sorting
|
||||
type: docs
|
||||
weight: 14
|
||||
---
|
||||
|
||||
# Sort
|
||||
# Sorting
|
||||
|
||||

|
||||
|
@ -16,6 +16,7 @@
|
||||
<a href="https://travis-ci.org/github/halfrost/LeetCode-Go" rel="nofollow"><img src="https://travis-ci.org/halfrost/LeetCode-Go.svg?branch=master"></a>
|
||||
<a href="https://goreportcard.com/report/github.com/halfrost/LeetCode-Go" rel="nofollow"><img src="https://goreportcard.com/badge/github.com/halfrost/LeetCode-Go"></a>
|
||||
<img src="https://img.shields.io/badge/runtime%20beats-100%25-success">
|
||||
<a href="https://codecov.io/gh/halfrost/LeetCode-Go"><img src="https://codecov.io/gh/halfrost/LeetCode-Go/branch/master/graph/badge.svg" /></a>
|
||||
<!--<img alt="GitHub go.mod Go version" src="https://img.shields.io/github/go-mod/go-version/halfrost/LeetCode-Go?color=26C2F0">-->
|
||||
<img alt="Support Go version" src="https://img.shields.io/badge/Go-v1.15-26C2F0">
|
||||
<img src="https://visitor-badge.laobi.icu/badge?page_id=halfrost.LeetCode-Go">
|
||||
|
@ -8,7 +8,7 @@ func lengthOfLongestSubstring(s string) int {
|
||||
var bitSet [256]bool
|
||||
result, left, right := 0, 0, 0
|
||||
for left < len(s) {
|
||||
// 右侧字符对应的bitSet被标记true,说明此字符在X位置重复,需要左侧向前移动,直到将X标记为false
|
||||
// 右侧字符对应的 bitSet 被标记 true,说明此字符在 X 位置重复,需要左侧向前移动,直到将 X 标记为 false
|
||||
if bitSet[s[right]] {
|
||||
bitSet[s[left]] = false
|
||||
left++
|
||||
@ -27,7 +27,7 @@ func lengthOfLongestSubstring(s string) int {
|
||||
}
|
||||
|
||||
// 解法二 滑动窗口
|
||||
func lengthOfLongestSubstring_(s string) int {
|
||||
func lengthOfLongestSubstring1(s string) int {
|
||||
if len(s) == 0 {
|
||||
return 0
|
||||
}
|
||||
@ -47,6 +47,21 @@ func lengthOfLongestSubstring_(s string) int {
|
||||
return result
|
||||
}
|
||||
|
||||
// 解法三 滑动窗口-哈希桶
|
||||
func lengthOfLongestSubstring2(s string) int {
|
||||
right, left, res := 0, 0, 0
|
||||
indexes := make(map[byte]int, len(s))
|
||||
for left < len(s) {
|
||||
if idx, ok := indexes[s[left]]; ok && idx >= right {
|
||||
right = idx + 1
|
||||
}
|
||||
indexes[s[left]] = left
|
||||
left++
|
||||
res = max(res, left-right)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func max(a int, b int) int {
|
||||
if a > b {
|
||||
return a
|
||||
|
@ -51,7 +51,7 @@ func Test_Problem3(t *testing.T) {
|
||||
|
||||
for _, q := range qs {
|
||||
_, p := q.ans3, q.para3
|
||||
fmt.Printf("【input】:%v 【output】:%v\n", p, lengthOfLongestSubstring_(p.s))
|
||||
fmt.Printf("【input】:%v 【output】:%v\n", p, lengthOfLongestSubstring(p.s))
|
||||
}
|
||||
fmt.Printf("\n\n\n")
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ You may assume **nums1** and **nums2** cannot be both empty.
|
||||
|
||||
|
||||
- 给出两个有序数组,要求找出这两个数组合并以后的有序数组中的中位数。要求时间复杂度为 O(log (m+n))。
|
||||
- 这一题最容易想到的办法是把两个数组合并,然后取出中位数。但是合并有序数组的操作是 `O(max(n,m))` 的,不符合题意。看到题目给的 `log` 的时间复杂度,很容易联想到二分搜索。
|
||||
- 这一题最容易想到的办法是把两个数组合并,然后取出中位数。但是合并有序数组的操作是 `O(m+n)` 的,不符合题意。看到题目给的 `log` 的时间复杂度,很容易联想到二分搜索。
|
||||
- 由于要找到最终合并以后数组的中位数,两个数组的总大小也知道,所以中间这个位置也是知道的。只需要二分搜索一个数组中切分的位置,另一个数组中切分的位置也能得到。为了使得时间复杂度最小,所以二分搜索两个数组中长度较小的那个数组。
|
||||
- 关键的问题是如何切分数组 1 和数组 2 。其实就是如何切分数组 1 。先随便二分产生一个 `midA`,切分的线何时算满足了中位数的条件呢?即,线左边的数都小于右边的数,即,`nums1[midA-1] ≤ nums2[midB] && nums2[midB-1] ≤ nums1[midA]` 。如果这些条件都不满足,切分线就需要调整。如果 `nums1[midA] < nums2[midB-1]`,说明 `midA` 这条线划分出来左边的数小了,切分线应该右移;如果 `nums1[midA-1] > nums2[midB]`,说明 midA 这条线划分出来左边的数大了,切分线应该左移。经过多次调整以后,切分线总能找到满足条件的解。
|
||||
- 假设现在找到了切分的两条线了,`数组 1` 在切分线两边的下标分别是 `midA - 1` 和 `midA`。`数组 2` 在切分线两边的下标分别是 `midB - 1` 和 `midB`。最终合并成最终数组,如果数组长度是奇数,那么中位数就是 `max(nums1[midA-1], nums2[midB-1])`。如果数组长度是偶数,那么中间位置的两个数依次是:`max(nums1[midA-1], nums2[midB-1])` 和 `min(nums1[midA], nums2[midB])`,那么中位数就是 `(max(nums1[midA-1], nums2[midB-1]) + min(nums1[midA], nums2[midB])) / 2`。图示见下图:
|
||||
|
@ -0,0 +1,117 @@
|
||||
package leetcode
|
||||
|
||||
// 解法一 Manacher's algorithm,时间复杂度 O(n),空间复杂度 O(n)
|
||||
func longestPalindrome(s string) string {
|
||||
if len(s) < 2 {
|
||||
return s
|
||||
}
|
||||
newS := make([]rune, 0)
|
||||
newS = append(newS, '#')
|
||||
for _, c := range s {
|
||||
newS = append(newS, c)
|
||||
newS = append(newS, '#')
|
||||
}
|
||||
// dp[i]: 以预处理字符串下标 i 为中心的回文半径(奇数长度时不包括中心)
|
||||
// maxRight: 通过中心扩散的方式能够扩散的最右边的下标
|
||||
// center: 与 maxRight 对应的中心字符的下标
|
||||
// maxLen: 记录最长回文串的半径
|
||||
// begin: 记录最长回文串在起始串 s 中的起始下标
|
||||
dp, maxRight, center, maxLen, begin := make([]int, len(newS)), 0, 0, 1, 0
|
||||
for i := 0; i < len(newS); i++ {
|
||||
if i < maxRight {
|
||||
// 这一行代码是 Manacher 算法的关键所在
|
||||
dp[i] = min(maxRight-i, dp[2*center-i])
|
||||
}
|
||||
// 中心扩散法更新 dp[i]
|
||||
left, right := i-(1+dp[i]), i+(1+dp[i])
|
||||
for left >= 0 && right < len(newS) && newS[left] == newS[right] {
|
||||
dp[i]++
|
||||
left--
|
||||
right++
|
||||
}
|
||||
// 更新 maxRight,它是遍历过的 i 的 i + dp[i] 的最大者
|
||||
if i+dp[i] > maxRight {
|
||||
maxRight = i + dp[i]
|
||||
center = i
|
||||
}
|
||||
// 记录最长回文子串的长度和相应它在原始字符串中的起点
|
||||
if dp[i] > maxLen {
|
||||
maxLen = dp[i]
|
||||
begin = (i - maxLen) / 2 // 这里要除以 2 因为有我们插入的辅助字符 #
|
||||
}
|
||||
}
|
||||
return s[begin : begin+maxLen]
|
||||
}
|
||||
|
||||
func min(x, y int) int {
|
||||
if x < y {
|
||||
return x
|
||||
}
|
||||
return y
|
||||
}
|
||||
|
||||
// 解法二 滑动窗口,时间复杂度 O(n^2),空间复杂度 O(1)
|
||||
func longestPalindrome1(s string) string {
|
||||
if len(s) == 0 {
|
||||
return ""
|
||||
}
|
||||
left, right, pl, pr := 0, -1, 0, 0
|
||||
for left < len(s) {
|
||||
// 移动到相同字母的最右边(如果有相同字母)
|
||||
for right+1 < len(s) && s[left] == s[right+1] {
|
||||
right++
|
||||
}
|
||||
// 找到回文的边界
|
||||
for left-1 >= 0 && right+1 < len(s) && s[left-1] == s[right+1] {
|
||||
left--
|
||||
right++
|
||||
}
|
||||
if right-left > pr-pl {
|
||||
pl, pr = left, right
|
||||
}
|
||||
// 重置到下一次寻找回文的中心
|
||||
left = (left+right)/2 + 1
|
||||
right = left
|
||||
}
|
||||
return s[pl : pr+1]
|
||||
}
|
||||
|
||||
// 解法三 中心扩散法,时间复杂度 O(n^2),空间复杂度 O(1)
|
||||
func longestPalindrome2(s string) string {
|
||||
res := ""
|
||||
for i := 0; i < len(s); i++ {
|
||||
res = maxPalindrome(s, i, i, res)
|
||||
res = maxPalindrome(s, i, i+1, res)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func maxPalindrome(s string, i, j int, res string) string {
|
||||
sub := ""
|
||||
for i >= 0 && j < len(s) && s[i] == s[j] {
|
||||
sub = s[i : j+1]
|
||||
i--
|
||||
j++
|
||||
}
|
||||
if len(res) < len(sub) {
|
||||
return sub
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// 解法四 DP,时间复杂度 O(n^2),空间复杂度 O(n^2)
|
||||
func longestPalindrome3(s string) string {
|
||||
res, dp := "", make([][]bool, len(s))
|
||||
for i := 0; i < len(s); i++ {
|
||||
dp[i] = make([]bool, len(s))
|
||||
}
|
||||
for i := len(s) - 1; i >= 0; i-- {
|
||||
for j := i; j < len(s); j++ {
|
||||
dp[i][j] = (s[i] == s[j]) && ((j-i < 3) || dp[i+1][j-1])
|
||||
if dp[i][j] && (res == "" || j-i+1 > len(res)) {
|
||||
res = s[i : j+1]
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type question5 struct {
|
||||
para5
|
||||
ans5
|
||||
}
|
||||
|
||||
// para 是参数
|
||||
// one 代表第一个参数
|
||||
type para5 struct {
|
||||
s string
|
||||
}
|
||||
|
||||
// ans 是答案
|
||||
// one 代表第一个答案
|
||||
type ans5 struct {
|
||||
one string
|
||||
}
|
||||
|
||||
func Test_Problem5(t *testing.T) {
|
||||
|
||||
qs := []question5{
|
||||
|
||||
{
|
||||
para5{"babad"},
|
||||
ans5{"bab"},
|
||||
},
|
||||
|
||||
{
|
||||
para5{"cbbd"},
|
||||
ans5{"bb"},
|
||||
},
|
||||
|
||||
{
|
||||
para5{"a"},
|
||||
ans5{"a"},
|
||||
},
|
||||
|
||||
{
|
||||
para5{"ac"},
|
||||
ans5{"a"},
|
||||
},
|
||||
|
||||
{
|
||||
para5{"aa"},
|
||||
ans5{"aa"},
|
||||
},
|
||||
|
||||
{
|
||||
para5{"ajgiljtperkvubjmdsefcylksrxtftqrehoitdgdtttswwttmfuvwgwrruuqmxttzsbmuhgfaoueumvbhajqsaxkkihjwevzzedizmrsmpxqavyryklbotwzngxscvyuqjkkaotitddlhhnutmotupwuwyltebtsdfssbwayuxrbgihmtphshdslktvsjadaykyjivbzhwujcdvzdxxfiixnzrmusqvwujjmxhbqbdpauacnzojnzxxgrkmupadfcsujkcwajsgintahwgbjnvjqubcxajdyyapposrkpqtpqfjcvbhlmwfutgognqxgaukpmdyaxghgoqkqnigcllachmwzrazwhpppmsodvxilrccfqgpkmdqhoorxpyjsrtbeeidsinpeyxxpsjnymxkouskyhenzgieybwkgzrhhrzgkwbyeigznehyksuokxmynjspxxyepnisdieebtrsjypxroohqdmkpgqfccrlixvdosmppphwzarzwmhcallcginqkqoghgxaydmpkuagxqngogtufwmlhbvcjfqptqpkrsoppayydjaxcbuqjvnjbgwhatnigsjawckjuscfdapumkrgxxznjozncauapdbqbhxmjjuwvqsumrznxiifxxdzvdcjuwhzbvijykyadajsvtklsdhshptmhigbrxuyawbssfdstbetlywuwputomtunhhlddtitoakkjquyvcsxgnzwtoblkyryvaqxpmsrmzidezzvewjhikkxasqjahbvmueuoafghumbszttxmquurrwgwvufmttwwstttdgdtioherqtftxrsklycfesdmjbuvkreptjligja"},
|
||||
ans5{"ajgiljtperkvubjmdsefcylksrxtftqrehoitdgdtttswwttmfuvwgwrruuqmxttzsbmuhgfaoueumvbhajqsaxkkihjwevzzedizmrsmpxqavyryklbotwzngxscvyuqjkkaotitddlhhnutmotupwuwyltebtsdfssbwayuxrbgihmtphshdslktvsjadaykyjivbzhwujcdvzdxxfiixnzrmusqvwujjmxhbqbdpauacnzojnzxxgrkmupadfcsujkcwajsgintahwgbjnvjqubcxajdyyapposrkpqtpqfjcvbhlmwfutgognqxgaukpmdyaxghgoqkqnigcllachmwzrazwhpppmsodvxilrccfqgpkmdqhoorxpyjsrtbeeidsinpeyxxpsjnymxkouskyhenzgieybwkgzrhhrzgkwbyeigznehyksuokxmynjspxxyepnisdieebtrsjypxroohqdmkpgqfccrlixvdosmppphwzarzwmhcallcginqkqoghgxaydmpkuagxqngogtufwmlhbvcjfqptqpkrsoppayydjaxcbuqjvnjbgwhatnigsjawckjuscfdapumkrgxxznjozncauapdbqbhxmjjuwvqsumrznxiifxxdzvdcjuwhzbvijykyadajsvtklsdhshptmhigbrxuyawbssfdstbetlywuwputomtunhhlddtitoakkjquyvcsxgnzwtoblkyryvaqxpmsrmzidezzvewjhikkxasqjahbvmueuoafghumbszttxmquurrwgwvufmttwwstttdgdtioherqtftxrsklycfesdmjbuvkreptjligja"},
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Printf("------------------------Leetcode Problem 5------------------------\n")
|
||||
|
||||
for _, q := range qs {
|
||||
_, p := q.ans5, q.para5
|
||||
fmt.Printf("【input】:%v 【output】:%v\n", p, longestPalindrome(p.s))
|
||||
}
|
||||
fmt.Printf("\n\n\n")
|
||||
}
|
186
leetcode/0005.Longest-Palindromic-Substring/README.md
Normal file
186
leetcode/0005.Longest-Palindromic-Substring/README.md
Normal file
@ -0,0 +1,186 @@
|
||||
# [5. Longest Palindromic Substring](https://leetcode.com/problems/longest-palindromic-substring/)
|
||||
|
||||
|
||||
## 题目
|
||||
|
||||
Given a string `s`, return *the longest palindromic substring* in `s`.
|
||||
|
||||
**Example 1:**
|
||||
|
||||
```
|
||||
Input: s = "babad"
|
||||
Output: "bab"
|
||||
Note: "aba" is also a valid answer.
|
||||
|
||||
```
|
||||
|
||||
**Example 2:**
|
||||
|
||||
```
|
||||
Input: s = "cbbd"
|
||||
Output: "bb"
|
||||
|
||||
```
|
||||
|
||||
**Example 3:**
|
||||
|
||||
```
|
||||
Input: s = "a"
|
||||
Output: "a"
|
||||
|
||||
```
|
||||
|
||||
**Example 4:**
|
||||
|
||||
```
|
||||
Input: s = "ac"
|
||||
Output: "a"
|
||||
|
||||
```
|
||||
|
||||
**Constraints:**
|
||||
|
||||
- `1 <= s.length <= 1000`
|
||||
- `s` consist of only digits and English letters (lower-case and/or upper-case),
|
||||
|
||||
## 题目大意
|
||||
|
||||
给你一个字符串 `s`,找到 `s` 中最长的回文子串。
|
||||
|
||||
## 解题思路
|
||||
|
||||
- 此题非常经典,并且有多种解法。
|
||||
- 解法一,动态规划。定义 `dp[i][j]` 表示从字符串第 `i` 个字符到第 `j` 个字符这一段子串是否是回文串。由回文串的性质可以得知,回文串去掉一头一尾相同的字符以后,剩下的还是回文串。所以状态转移方程是 `dp[i][j] = (s[i] == s[j]) && ((j-i < 3) || dp[i+1][j-1])`,注意特殊的情况,`j - i == 1` 的时候,即只有 2 个字符的情况,只需要判断这 2 个字符是否相同即可。`j - i == 2` 的时候,即只有 3 个字符的情况,只需要判断除去中心以外对称的 2 个字符是否相等。每次循环动态维护保存最长回文串即可。时间复杂度 O(n^2),空间复杂度 O(n^2)。
|
||||
- 解法二,中心扩散法。动态规划的方法中,我们将任意起始,终止范围内的字符串都判断了一遍。其实没有这个必要,如果不是最长回文串,无需判断并保存结果。所以动态规划的方法在空间复杂度上还有优化空间。判断回文有一个核心问题是找到“轴心”。如果长度是偶数,那么轴心是中心虚拟的,如果长度是奇数,那么轴心正好是正中心的那个字母。中心扩散法的思想是枚举每个轴心的位置。然后做两次假设,假设最长回文串是偶数,那么以虚拟中心往 2 边扩散;假设最长回文串是奇数,那么以正中心的字符往 2 边扩散。扩散的过程就是对称判断两边字符是否相等的过程。这个方法时间复杂度和动态规划是一样的,但是空间复杂度降低了。时间复杂度 O(n^2),空间复杂度 O(1)。
|
||||
- 解法三,滑动窗口。这个写法其实就是中心扩散法变了一个写法。中心扩散是依次枚举每一个轴心。滑动窗口的方法稍微优化了一点,有些轴心两边字符不相等,下次就不会枚举这些不可能形成回文子串的轴心了。不过这点优化并没有优化时间复杂度,时间复杂度 O(n^2),空间复杂度 O(1)。
|
||||
- 解法四,马拉车算法。这个算法是本题的最优解,也是最复杂的解法。时间复杂度 O(n),空间复杂度 O(n)。中心扩散法有 2 处有重复判断,第一处是每次都往两边扩散,不同中心扩散多次,实际上有很多重复判断的字符,能否不重复判断?第二处,中心能否跳跃选择,不是每次都枚举,是否可以利用前一次的信息,跳跃选择下一次的中心?马拉车算法针对重复判断的问题做了优化,增加了一个辅助数组,将时间复杂度从 O(n^2) 优化到了 O(n),空间换了时间,空间复杂度增加到 O(n)。
|
||||
|
||||

|
||||
|
||||
- 首先是预处理,向字符串的头尾以及每两个字符中间添加一个特殊字符 `#`,比如字符串 `aaba` 处理后会变成 `#a#a#b#a#`。那么原先长度为偶数的回文字符串 `aa` 会变成长度为奇数的回文字符串 `#a#a#`,而长度为奇数的回文字符串 `aba` 会变成长度仍然为奇数的回文字符串 `#a#b#a#`,经过预处理以后,都会变成长度为奇数的字符串。**注意这里的特殊字符不需要是没有出现过的字母,也可以使用任何一个字符来作为这个特殊字符。**这是因为,当我们只考虑长度为奇数的回文字符串时,每次我们比较的两个字符奇偶性一定是相同的,所以原来字符串中的字符不会与插入的特殊字符互相比较,不会因此产生问题。**预处理以后,以某个中心扩散的步数和实际字符串长度是相等的。**因为半径里面包含了插入的特殊字符,又由于左右对称的性质,所以扩散半径就等于原来回文子串的长度。
|
||||
|
||||

|
||||
|
||||
- 核心部分是如何通过左边已经扫描过的数据推出右边下一次要扩散的中心。这里定义下一次要扩散的中心下标是 `i`。如果 `i` 比 `maxRight` 要小,只能继续中心扩散。如果 `i` 比 `maxRight` 大,这是又分为 3 种情况。三种情况见上图。将上述 3 种情况总结起来,就是 :`dp[i] = min(maxRight-i, dp[2*center-i])`,其中,`mirror` 相对于 `center` 是和 `i` 中心对称的,所以它的下标可以计算出来是 `2*center-i`。更新完 `dp[i]` 以后,就要进行中心扩散了。中心扩散以后动态维护最长回文串并相应的更新 `center`,`maxRight`,并且记录下原始字符串的起始位置 `begin` 和 `maxLen`。
|
||||
|
||||
## 代码
|
||||
|
||||
```go
|
||||
package leetcode
|
||||
|
||||
// 解法一 Manacher's algorithm,时间复杂度 O(n),空间复杂度 O(n)
|
||||
func longestPalindrome(s string) string {
|
||||
if len(s) < 2 {
|
||||
return s
|
||||
}
|
||||
newS := make([]rune, 0)
|
||||
newS = append(newS, '#')
|
||||
for _, c := range s {
|
||||
newS = append(newS, c)
|
||||
newS = append(newS, '#')
|
||||
}
|
||||
// dp[i]: 以预处理字符串下标 i 为中心的回文半径(奇数长度时不包括中心)
|
||||
// maxRight: 通过中心扩散的方式能够扩散的最右边的下标
|
||||
// center: 与 maxRight 对应的中心字符的下标
|
||||
// maxLen: 记录最长回文串的半径
|
||||
// begin: 记录最长回文串在起始串 s 中的起始下标
|
||||
dp, maxRight, center, maxLen, begin := make([]int, len(newS)), 0, 0, 1, 0
|
||||
for i := 0; i < len(newS); i++ {
|
||||
if i < maxRight {
|
||||
// 这一行代码是 Manacher 算法的关键所在
|
||||
dp[i] = min(maxRight-i, dp[2*center-i])
|
||||
}
|
||||
// 中心扩散法更新 dp[i]
|
||||
left, right := i-(1+dp[i]), i+(1+dp[i])
|
||||
for left >= 0 && right < len(newS) && newS[left] == newS[right] {
|
||||
dp[i]++
|
||||
left--
|
||||
right++
|
||||
}
|
||||
// 更新 maxRight,它是遍历过的 i 的 i + dp[i] 的最大者
|
||||
if i+dp[i] > maxRight {
|
||||
maxRight = i + dp[i]
|
||||
center = i
|
||||
}
|
||||
// 记录最长回文子串的长度和相应它在原始字符串中的起点
|
||||
if dp[i] > maxLen {
|
||||
maxLen = dp[i]
|
||||
begin = (i - maxLen) / 2 // 这里要除以 2 因为有我们插入的辅助字符 #
|
||||
}
|
||||
}
|
||||
return s[begin : begin+maxLen]
|
||||
}
|
||||
|
||||
func min(x, y int) int {
|
||||
if x < y {
|
||||
return x
|
||||
}
|
||||
return y
|
||||
}
|
||||
|
||||
// 解法二 滑动窗口,时间复杂度 O(n^2),空间复杂度 O(1)
|
||||
func longestPalindrome1(s string) string {
|
||||
if len(s) == 0 {
|
||||
return ""
|
||||
}
|
||||
left, right, pl, pr := 0, -1, 0, 0
|
||||
for left < len(s) {
|
||||
// 移动到相同字母的最右边(如果有相同字母)
|
||||
for right+1 < len(s) && s[left] == s[right+1] {
|
||||
right++
|
||||
}
|
||||
// 找到回文的边界
|
||||
for left-1 >= 0 && right+1 < len(s) && s[left-1] == s[right+1] {
|
||||
left--
|
||||
right++
|
||||
}
|
||||
if right-left > pr-pl {
|
||||
pl, pr = left, right
|
||||
}
|
||||
// 重置到下一次寻找回文的中心
|
||||
left = (left+right)/2 + 1
|
||||
right = left
|
||||
}
|
||||
return s[pl : pr+1]
|
||||
}
|
||||
|
||||
// 解法三 中心扩散法,时间复杂度 O(n^2),空间复杂度 O(1)
|
||||
func longestPalindrome2(s string) string {
|
||||
res := ""
|
||||
for i := 0; i < len(s); i++ {
|
||||
res = maxPalindrome(s, i, i, res)
|
||||
res = maxPalindrome(s, i, i+1, res)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func maxPalindrome(s string, i, j int, res string) string {
|
||||
sub := ""
|
||||
for i >= 0 && j < len(s) && s[i] == s[j] {
|
||||
sub = s[i : j+1]
|
||||
i--
|
||||
j++
|
||||
}
|
||||
if len(res) < len(sub) {
|
||||
return sub
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// 解法四 DP,时间复杂度 O(n^2),空间复杂度 O(n^2)
|
||||
func longestPalindrome3(s string) string {
|
||||
res, dp := "", make([][]bool, len(s))
|
||||
for i := 0; i < len(s); i++ {
|
||||
dp[i] = make([]bool, len(s))
|
||||
}
|
||||
for i := len(s) - 1; i >= 0; i-- {
|
||||
for j := i; j < len(s); j++ {
|
||||
dp[i][j] = (s[i] == s[j]) && ((j-i < 3) || dp[i+1][j-1])
|
||||
if dp[i][j] && (res == "" || j-i+1 > len(res)) {
|
||||
res = s[i : j+1]
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
```
|
26
leetcode/0006.ZigZag-Conversion/6. ZigZag Conversion.go
Normal file
26
leetcode/0006.ZigZag-Conversion/6. ZigZag Conversion.go
Normal file
@ -0,0 +1,26 @@
|
||||
package leetcode
|
||||
|
||||
func convert(s string, numRows int) string {
|
||||
matrix, down, up := make([][]byte, numRows, numRows), 0, numRows-2
|
||||
for i := 0; i != len(s); {
|
||||
if down != numRows {
|
||||
matrix[down] = append(matrix[down], byte(s[i]))
|
||||
down++
|
||||
i++
|
||||
} else if up > 0 {
|
||||
matrix[up] = append(matrix[up], byte(s[i]))
|
||||
up--
|
||||
i++
|
||||
} else {
|
||||
up = numRows - 2
|
||||
down = 0
|
||||
}
|
||||
}
|
||||
solution := make([]byte, 0, len(s))
|
||||
for _, row := range matrix {
|
||||
for _, item := range row {
|
||||
solution = append(solution, item)
|
||||
}
|
||||
}
|
||||
return string(solution)
|
||||
}
|
53
leetcode/0006.ZigZag-Conversion/6. ZigZag Conversion_test.go
Normal file
53
leetcode/0006.ZigZag-Conversion/6. ZigZag Conversion_test.go
Normal file
@ -0,0 +1,53 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type question6 struct {
|
||||
para6
|
||||
ans6
|
||||
}
|
||||
|
||||
// para 是参数
|
||||
// one 代表第一个参数
|
||||
type para6 struct {
|
||||
s string
|
||||
numRows int
|
||||
}
|
||||
|
||||
// ans 是答案
|
||||
// one 代表第一个答案
|
||||
type ans6 struct {
|
||||
one string
|
||||
}
|
||||
|
||||
func Test_Problem6(t *testing.T) {
|
||||
|
||||
qs := []question6{
|
||||
|
||||
{
|
||||
para6{"PAYPALISHIRING", 3},
|
||||
ans6{"PAHNAPLSIIGYIR"},
|
||||
},
|
||||
|
||||
{
|
||||
para6{"PAYPALISHIRING", 4},
|
||||
ans6{"PINALSIGYAHRPI"},
|
||||
},
|
||||
|
||||
{
|
||||
para6{"A", 1},
|
||||
ans6{"A"},
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Printf("------------------------Leetcode Problem 6------------------------\n")
|
||||
|
||||
for _, q := range qs {
|
||||
_, p := q.ans6, q.para6
|
||||
fmt.Printf("【input】:%v 【output】:%v\n", p, convert(p.s, p.numRows))
|
||||
}
|
||||
fmt.Printf("\n\n\n")
|
||||
}
|
107
leetcode/0006.ZigZag-Conversion/README.md
Normal file
107
leetcode/0006.ZigZag-Conversion/README.md
Normal file
@ -0,0 +1,107 @@
|
||||
# [6. ZigZag Conversion](https://leetcode.com/problems/zigzag-conversion/)
|
||||
|
||||
|
||||
## 题目
|
||||
|
||||
The string `"PAYPALISHIRING"` is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)
|
||||
|
||||
```
|
||||
P A H N
|
||||
A P L S I I G
|
||||
Y I R
|
||||
```
|
||||
|
||||
And then read line by line: `"PAHNAPLSIIGYIR"`
|
||||
|
||||
Write the code that will take a string and make this conversion given a number of rows:
|
||||
|
||||
```
|
||||
string convert(string s, int numRows);
|
||||
```
|
||||
|
||||
**Example 1:**
|
||||
|
||||
```
|
||||
Input: s = "PAYPALISHIRING", numRows = 3
|
||||
Output: "PAHNAPLSIIGYIR"
|
||||
```
|
||||
|
||||
**Example 2:**
|
||||
|
||||
```
|
||||
Input: s = "PAYPALISHIRING", numRows = 4
|
||||
Output: "PINALSIGYAHRPI"
|
||||
Explanation:
|
||||
P I N
|
||||
A L S I G
|
||||
Y A H R
|
||||
P I
|
||||
```
|
||||
|
||||
**Example 3:**
|
||||
|
||||
```
|
||||
Input: s = "A", numRows = 1
|
||||
Output: "A"
|
||||
```
|
||||
|
||||
**Constraints:**
|
||||
|
||||
- `1 <= s.length <= 1000`
|
||||
- `s` consists of English letters (lower-case and upper-case), `','` and `'.'`.
|
||||
- `1 <= numRows <= 1000`
|
||||
|
||||
## 题目大意
|
||||
|
||||
将一个给定字符串 `s` 根据给定的行数 `numRows` ,以从上往下、从左到右进行 Z 字形排列。
|
||||
|
||||
比如输入字符串为 `"PAYPALISHIRING"` 行数为 3 时,排列如下:
|
||||
|
||||
```go
|
||||
P A H N
|
||||
A P L S I I G
|
||||
Y I R
|
||||
```
|
||||
|
||||
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:`"PAHNAPLSIIGYIR"`。
|
||||
|
||||
请你实现这个将字符串进行指定行数变换的函数:
|
||||
|
||||
```go
|
||||
string convert(string s, int numRows);
|
||||
```
|
||||
|
||||
## 解题思路
|
||||
|
||||
- 这一题没有什么算法思想,考察的是对程序控制的能力。用 2 个变量保存方向,当垂直输出的行数达到了规定的目标行数以后,需要从下往上转折到第一行,循环中控制好方向ji
|
||||
|
||||
## 代码
|
||||
|
||||
```go
|
||||
package leetcode
|
||||
|
||||
func convert(s string, numRows int) string {
|
||||
matrix, down, up := make([][]byte, numRows, numRows), 0, numRows-2
|
||||
for i := 0; i != len(s); {
|
||||
if down != numRows {
|
||||
matrix[down] = append(matrix[down], byte(s[i]))
|
||||
down++
|
||||
i++
|
||||
} else if up > 0 {
|
||||
matrix[up] = append(matrix[up], byte(s[i]))
|
||||
up--
|
||||
i++
|
||||
} else {
|
||||
up = numRows - 2
|
||||
down = 0
|
||||
}
|
||||
}
|
||||
solution := make([]byte, 0, len(s))
|
||||
for _, row := range matrix {
|
||||
for _, item := range row {
|
||||
solution = append(solution, item)
|
||||
}
|
||||
}
|
||||
return string(solution)
|
||||
}
|
||||
```
|
@ -0,0 +1,56 @@
|
||||
package leetcode
|
||||
|
||||
func myAtoi(s string) int {
|
||||
maxInt, signAllowed, whitespaceAllowed, sign, digits := int64(2<<30), true, true, 1, []int{}
|
||||
for _, c := range s {
|
||||
if c == ' ' && whitespaceAllowed {
|
||||
continue
|
||||
}
|
||||
if signAllowed {
|
||||
if c == '+' {
|
||||
signAllowed = false
|
||||
whitespaceAllowed = false
|
||||
continue
|
||||
} else if c == '-' {
|
||||
sign = -1
|
||||
signAllowed = false
|
||||
whitespaceAllowed = false
|
||||
continue
|
||||
}
|
||||
}
|
||||
if c < '0' || c > '9' {
|
||||
break
|
||||
}
|
||||
whitespaceAllowed, signAllowed = false, false
|
||||
digits = append(digits, int(c-48))
|
||||
}
|
||||
var num, place int64
|
||||
place, num = 1, 0
|
||||
lastLeading0Index := -1
|
||||
for i, d := range digits {
|
||||
if d == 0 {
|
||||
lastLeading0Index = i
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
if lastLeading0Index > -1 {
|
||||
digits = digits[lastLeading0Index+1:]
|
||||
}
|
||||
var rtnMax int64
|
||||
if sign > 0 {
|
||||
rtnMax = maxInt - 1
|
||||
} else {
|
||||
rtnMax = maxInt
|
||||
}
|
||||
digitsCount := len(digits)
|
||||
for i := digitsCount - 1; i >= 0; i-- {
|
||||
num += int64(digits[i]) * place
|
||||
place *= 10
|
||||
if digitsCount-i > 10 || num > rtnMax {
|
||||
return int(int64(sign) * rtnMax)
|
||||
}
|
||||
}
|
||||
num *= int64(sign)
|
||||
return int(num)
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type question8 struct {
|
||||
para8
|
||||
ans8
|
||||
}
|
||||
|
||||
// para 是参数
|
||||
// one 代表第一个参数
|
||||
type para8 struct {
|
||||
one string
|
||||
}
|
||||
|
||||
// ans 是答案
|
||||
// one 代表第一个答案
|
||||
type ans8 struct {
|
||||
one int
|
||||
}
|
||||
|
||||
func Test_Problem8(t *testing.T) {
|
||||
|
||||
qs := []question8{
|
||||
|
||||
{
|
||||
para8{"42"},
|
||||
ans8{42},
|
||||
},
|
||||
|
||||
{
|
||||
para8{" -42"},
|
||||
ans8{-42},
|
||||
},
|
||||
|
||||
{
|
||||
para8{"4193 with words"},
|
||||
ans8{4193},
|
||||
},
|
||||
|
||||
{
|
||||
para8{"words and 987"},
|
||||
ans8{0},
|
||||
},
|
||||
|
||||
{
|
||||
para8{"-91283472332"},
|
||||
ans8{-2147483648},
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Printf("------------------------Leetcode Problem 8------------------------\n")
|
||||
|
||||
for _, q := range qs {
|
||||
_, p := q.ans8, q.para8
|
||||
fmt.Printf("【input】:%v 【output】:%v\n", p.one, myAtoi(p.one))
|
||||
}
|
||||
fmt.Printf("\n\n\n")
|
||||
}
|
192
leetcode/0008.String-to-Integer-atoi/README.md
Normal file
192
leetcode/0008.String-to-Integer-atoi/README.md
Normal file
@ -0,0 +1,192 @@
|
||||
# [8. String to Integer (atoi)](https://leetcode.com/problems/string-to-integer-atoi/)
|
||||
|
||||
|
||||
## 题目
|
||||
|
||||
Implement the `myAtoi(string s)` function, which converts a string to a 32-bit signed integer (similar to C/C++'s `atoi` function).
|
||||
|
||||
The algorithm for `myAtoi(string s)` is as follows:
|
||||
|
||||
1. Read in and ignore any leading whitespace.
|
||||
2. Check if the next character (if not already at the end of the string) is `'-'` or `'+'`. Read this character in if it is either. This determines if the final result is negative or positive respectively. Assume the result is positive if neither is present.
|
||||
3. Read in next the characters until the next non-digit charcter or the end of the input is reached. The rest of the string is ignored.
|
||||
4. Convert these digits into an integer (i.e. `"123" -> 123`, `"0032" -> 32`). If no digits were read, then the integer is `0`. Change the sign as necessary (from step 2).
|
||||
5. If the integer is out of the 32-bit signed integer range `[-231, 231 - 1]`, then clamp the integer so that it remains in the range. Specifically, integers less than `231` should be clamped to `231`, and integers greater than `231 - 1` should be clamped to `231 - 1`.
|
||||
6. Return the integer as the final result.
|
||||
|
||||
**Note:**
|
||||
|
||||
- Only the space character `' '` is considered a whitespace character.
|
||||
- **Do not ignore** any characters other than the leading whitespace or the rest of the string after the digits.
|
||||
|
||||
**Example 1:**
|
||||
|
||||
```
|
||||
Input: s = "42"
|
||||
Output: 42
|
||||
Explanation: The underlined characters are what is read in, the caret is the current reader position.
|
||||
Step 1: "42" (no characters read because there is no leading whitespace)
|
||||
^
|
||||
Step 2: "42" (no characters read because there is neither a '-' nor '+')
|
||||
^
|
||||
Step 3: "42" ("42" is read in)
|
||||
^
|
||||
The parsed integer is 42.
|
||||
Since 42 is in the range [-231, 231 - 1], the final result is 42.
|
||||
|
||||
```
|
||||
|
||||
**Example 2:**
|
||||
|
||||
```
|
||||
Input: s = " -42"
|
||||
Output: -42
|
||||
Explanation:
|
||||
Step 1: " -42" (leading whitespace is read and ignored)
|
||||
^
|
||||
Step 2: " -42" ('-' is read, so the result should be negative)
|
||||
^
|
||||
Step 3: " -42" ("42" is read in)
|
||||
^
|
||||
The parsed integer is -42.
|
||||
Since -42 is in the range [-231, 231 - 1], the final result is -42.
|
||||
|
||||
```
|
||||
|
||||
**Example 3:**
|
||||
|
||||
```
|
||||
Input: s = "4193 with words"
|
||||
Output: 4193
|
||||
Explanation:
|
||||
Step 1: "4193 with words" (no characters read because there is no leading whitespace)
|
||||
^
|
||||
Step 2: "4193 with words" (no characters read because there is neither a '-' nor '+')
|
||||
^
|
||||
Step 3: "4193 with words" ("4193" is read in; reading stops because the next character is a non-digit)
|
||||
^
|
||||
The parsed integer is 4193.
|
||||
Since 4193 is in the range [-231, 231 - 1], the final result is 4193.
|
||||
|
||||
```
|
||||
|
||||
**Example 4:**
|
||||
|
||||
```
|
||||
Input: s = "words and 987"
|
||||
Output: 0
|
||||
Explanation:
|
||||
Step 1: "words and 987" (no characters read because there is no leading whitespace)
|
||||
^
|
||||
Step 2: "words and 987" (no characters read because there is neither a '-' nor '+')
|
||||
^
|
||||
Step 3: "words and 987" (reading stops immediately because there is a non-digit 'w')
|
||||
^
|
||||
The parsed integer is 0 because no digits were read.
|
||||
Since 0 is in the range [-231, 231 - 1], the final result is 0.
|
||||
|
||||
```
|
||||
|
||||
**Example 5:**
|
||||
|
||||
```
|
||||
Input: s = "-91283472332"
|
||||
Output: -2147483648
|
||||
Explanation:
|
||||
Step 1: "-91283472332" (no characters read because there is no leading whitespace)
|
||||
^
|
||||
Step 2: "-91283472332" ('-' is read, so the result should be negative)
|
||||
^
|
||||
Step 3: "-91283472332" ("91283472332" is read in)
|
||||
^
|
||||
The parsed integer is -91283472332.
|
||||
Since -91283472332 is less than the lower bound of the range [-231, 231 - 1], the final result is clamped to -231 = -2147483648.
|
||||
```
|
||||
|
||||
**Constraints:**
|
||||
|
||||
- `0 <= s.length <= 200`
|
||||
- `s` consists of English letters (lower-case and upper-case), digits (`0-9`), `' '`, `'+'`
|
||||
|
||||
## 题目大意
|
||||
|
||||
请你来实现一个 myAtoi(string s) 函数,使其能将字符串转换成一个 32 位有符号整数(类似 C/C++ 中的 atoi 函数)。
|
||||
|
||||
函数 myAtoi(string s) 的算法如下:
|
||||
|
||||
- 读入字符串并丢弃无用的前导空格
|
||||
- 检查下一个字符(假设还未到字符末尾)为正还是负号,读取该字符(如果有)。 确定最终结果是负数还是正数。 如果两者都不存在,则假定结果为正。
|
||||
- 读入下一个字符,直到到达下一个非数字字符或到达输入的结尾。字符串的其余部分将被忽略。
|
||||
- 将前面步骤读入的这些数字转换为整数(即,"123" -> 123, "0032" -> 32)。如果没有读入数字,则整数为 0 。必要时更改符号(从步骤 2 开始)。
|
||||
- 如果整数数超过 32 位有符号整数范围 [−231, 231 − 1] ,需要截断这个整数,使其保持在这个范围内。具体来说,小于 −231 的整数应该被固定为 −231 ,大于 231 − 1 的整数应该被固定为 231 − 1 。
|
||||
- 返回整数作为最终结果。
|
||||
|
||||
注意:
|
||||
|
||||
- 本题中的空白字符只包括空格字符 ' ' 。
|
||||
- 除前导空格或数字后的其余字符串外,请勿忽略 任何其他字符。
|
||||
|
||||
## 解题思路
|
||||
|
||||
- 这题是简单题。题目要求实现类似 `C++` 中 `atoi` 函数的功能。这个函数功能是将字符串类型的数字转成 `int` 类型数字。先去除字符串中的前导空格,并判断记录数字的符号。数字需要去掉前导 `0` 。最后将数字转换成数字类型,判断是否超过 `int` 类型的上限 `[-2^31, 2^31 - 1]`,如果超过上限,需要输出边界,即 `-2^31`,或者 `2^31 - 1`。
|
||||
|
||||
## 代码
|
||||
|
||||
```go
|
||||
package leetcode
|
||||
|
||||
func myAtoi(s string) int {
|
||||
maxInt, signAllowed, whitespaceAllowed, sign, digits := int64(2<<30), true, true, 1, []int{}
|
||||
for _, c := range s {
|
||||
if c == ' ' && whitespaceAllowed {
|
||||
continue
|
||||
}
|
||||
if signAllowed {
|
||||
if c == '+' {
|
||||
signAllowed = false
|
||||
whitespaceAllowed = false
|
||||
continue
|
||||
} else if c == '-' {
|
||||
sign = -1
|
||||
signAllowed = false
|
||||
whitespaceAllowed = false
|
||||
continue
|
||||
}
|
||||
}
|
||||
if c < '0' || c > '9' {
|
||||
break
|
||||
}
|
||||
whitespaceAllowed, signAllowed = false, false
|
||||
digits = append(digits, int(c-48))
|
||||
}
|
||||
var num, place int64
|
||||
place, num = 1, 0
|
||||
lastLeading0Index := -1
|
||||
for i, d := range digits {
|
||||
if d == 0 {
|
||||
lastLeading0Index = i
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
if lastLeading0Index > -1 {
|
||||
digits = digits[lastLeading0Index+1:]
|
||||
}
|
||||
var rtnMax int64
|
||||
if sign > 0 {
|
||||
rtnMax = maxInt - 1
|
||||
} else {
|
||||
rtnMax = maxInt
|
||||
}
|
||||
digitsCount := len(digits)
|
||||
for i := digitsCount - 1; i >= 0; i-- {
|
||||
num += int64(digits[i]) * place
|
||||
place *= 10
|
||||
if digitsCount-i > 10 || num > rtnMax {
|
||||
return int(int64(sign) * rtnMax)
|
||||
}
|
||||
}
|
||||
num *= int64(sign)
|
||||
return int(num)
|
||||
}
|
||||
```
|
@ -2,7 +2,33 @@ package leetcode
|
||||
|
||||
import "strconv"
|
||||
|
||||
// 解法一
|
||||
func isPalindrome(x int) bool {
|
||||
if x < 0 {
|
||||
return false
|
||||
}
|
||||
if x == 0 {
|
||||
return true
|
||||
}
|
||||
if x%10 == 0 {
|
||||
return false
|
||||
}
|
||||
arr := make([]int, 0, 32)
|
||||
for x > 0 {
|
||||
arr = append(arr, x%10)
|
||||
x = x / 10
|
||||
}
|
||||
sz := len(arr)
|
||||
for i, j := 0, sz-1; i <= j; i, j = i+1, j-1 {
|
||||
if arr[i] != arr[j] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// 解法二 数字转字符串
|
||||
func isPalindrome1(x int) bool {
|
||||
if x < 0 {
|
||||
return false
|
||||
}
|
||||
|
@ -49,7 +49,33 @@ package leetcode
|
||||
|
||||
import "strconv"
|
||||
|
||||
// 解法一
|
||||
func isPalindrome(x int) bool {
|
||||
if x < 0 {
|
||||
return false
|
||||
}
|
||||
if x == 0 {
|
||||
return true
|
||||
}
|
||||
if x%10 == 0 {
|
||||
return false
|
||||
}
|
||||
arr := make([]int, 0, 32)
|
||||
for x > 0 {
|
||||
arr = append(arr, x%10)
|
||||
x = x / 10
|
||||
}
|
||||
sz := len(arr)
|
||||
for i, j := 0, sz-1; i <= j; i, j = i+1, j-1 {
|
||||
if arr[i] != arr[j] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// 解法二 数字转字符串
|
||||
func isPalindrome1(x int) bool {
|
||||
if x < 0 {
|
||||
return false
|
||||
}
|
||||
@ -66,4 +92,5 @@ func isPalindrome(x int) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
```
|
15
leetcode/0012.Integer-to-Roman/12. Integer to Roman.go
Normal file
15
leetcode/0012.Integer-to-Roman/12. Integer to Roman.go
Normal file
@ -0,0 +1,15 @@
|
||||
package leetcode
|
||||
|
||||
func intToRoman(num int) string {
|
||||
values := []int{1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}
|
||||
symbols := []string{"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"}
|
||||
res, i := "", 0
|
||||
for num != 0 {
|
||||
for values[i] > num {
|
||||
i++
|
||||
}
|
||||
num -= values[i]
|
||||
res += symbols[i]
|
||||
}
|
||||
return res
|
||||
}
|
71
leetcode/0012.Integer-to-Roman/12. Integer to Roman_test.go
Normal file
71
leetcode/0012.Integer-to-Roman/12. Integer to Roman_test.go
Normal file
@ -0,0 +1,71 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type question12 struct {
|
||||
para12
|
||||
ans12
|
||||
}
|
||||
|
||||
// para 是参数
|
||||
// one 代表第一个参数
|
||||
type para12 struct {
|
||||
one int
|
||||
}
|
||||
|
||||
// ans 是答案
|
||||
// one 代表第一个答案
|
||||
type ans12 struct {
|
||||
one string
|
||||
}
|
||||
|
||||
func Test_Problem12(t *testing.T) {
|
||||
|
||||
qs := []question12{
|
||||
|
||||
{
|
||||
para12{3},
|
||||
ans12{"III"},
|
||||
},
|
||||
|
||||
{
|
||||
para12{4},
|
||||
ans12{"IV"},
|
||||
},
|
||||
|
||||
{
|
||||
para12{9},
|
||||
ans12{"IX"},
|
||||
},
|
||||
|
||||
{
|
||||
para12{58},
|
||||
ans12{"LVIII"},
|
||||
},
|
||||
|
||||
{
|
||||
para12{1994},
|
||||
ans12{"MCMXCIV"},
|
||||
},
|
||||
{
|
||||
para12{123},
|
||||
ans12{"CXXIII"},
|
||||
},
|
||||
|
||||
{
|
||||
para12{120},
|
||||
ans12{"CXX"},
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Printf("------------------------Leetcode Problem 12------------------------\n")
|
||||
|
||||
for _, q := range qs {
|
||||
_, p := q.ans12, q.para12
|
||||
fmt.Printf("【input】:%v 【output】:%v\n", p.one, intToRoman(p.one))
|
||||
}
|
||||
fmt.Printf("\n\n\n")
|
||||
}
|
102
leetcode/0012.Integer-to-Roman/README.md
Normal file
102
leetcode/0012.Integer-to-Roman/README.md
Normal file
@ -0,0 +1,102 @@
|
||||
# [12. Integer to Roman](https://leetcode.com/problems/integer-to-roman/)
|
||||
|
||||
|
||||
## 题目
|
||||
|
||||
Roman numerals are represented by seven different symbols: `I`, `V`, `X`, `L`, `C`, `D` and `M`.
|
||||
|
||||
```
|
||||
Symbol Value
|
||||
I 1
|
||||
V 5
|
||||
X 10
|
||||
L 50
|
||||
C 100
|
||||
D 500
|
||||
M 1000
|
||||
```
|
||||
|
||||
For example, `2` is written as `II` in Roman numeral, just two one's added together. `12` is written as `XII`, which is simply `X + II`. The number `27` is written as `XXVII`, which is `XX + V + II`.
|
||||
|
||||
Roman numerals are usually written largest to smallest from left to right. However, the numeral for four is not `IIII`. Instead, the number four is written as `IV`. Because the one is before the five we subtract it making four. The same principle applies to the number nine, which is written as `IX`. There are six instances where subtraction is used:
|
||||
|
||||
- `I` can be placed before `V` (5) and `X` (10) to make 4 and 9.
|
||||
- `X` can be placed before `L` (50) and `C` (100) to make 40 and 90.
|
||||
- `C` can be placed before `D` (500) and `M` (1000) to make 400 and 900.
|
||||
|
||||
Given an integer, convert it to a roman numeral.
|
||||
|
||||
**Example 1:**
|
||||
|
||||
```
|
||||
Input: num = 3
|
||||
Output: "III"
|
||||
```
|
||||
|
||||
**Example 2:**
|
||||
|
||||
```
|
||||
Input: num = 4
|
||||
Output: "IV"
|
||||
```
|
||||
|
||||
**Example 3:**
|
||||
|
||||
```
|
||||
Input: num = 9
|
||||
Output: "IX"
|
||||
```
|
||||
|
||||
**Example 4:**
|
||||
|
||||
```
|
||||
Input: num = 58
|
||||
Output: "LVIII"
|
||||
Explanation: L = 50, V = 5, III = 3.
|
||||
```
|
||||
|
||||
**Example 5:**
|
||||
|
||||
```
|
||||
Input: num = 1994
|
||||
Output: "MCMXCIV"
|
||||
Explanation: M = 1000, CM = 900, XC = 90 and IV = 4.
|
||||
```
|
||||
|
||||
**Constraints:**
|
||||
|
||||
- `1 <= num <= 3999`
|
||||
|
||||
## 题目大意
|
||||
|
||||
通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:
|
||||
|
||||
- I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
|
||||
- X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
|
||||
- C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
|
||||
|
||||
给定一个整数,将其转为罗马数字。输入确保在 1 到 3999 的范围内。
|
||||
|
||||
## 解题思路
|
||||
|
||||
- 依照题意,优先选择大的数字,解题思路采用贪心算法。将 1-3999 范围内的罗马数字从大到小放在数组中,从头选择到尾,即可把整数转成罗马数字。
|
||||
|
||||
## 代码
|
||||
|
||||
```go
|
||||
package leetcode
|
||||
|
||||
func intToRoman(num int) string {
|
||||
values := []int{1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}
|
||||
symbols := []string{"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"}
|
||||
res, i := "", 0
|
||||
for num != 0 {
|
||||
for values[i] > num {
|
||||
i++
|
||||
}
|
||||
num -= values[i]
|
||||
res += symbols[i]
|
||||
}
|
||||
return res
|
||||
}
|
||||
```
|
@ -11,6 +11,9 @@ func threeSumClosest(nums []int, target int) int {
|
||||
if n > 2 {
|
||||
sort.Ints(nums)
|
||||
for i := 0; i < n-2; i++ {
|
||||
if i > 0 && nums[i] == nums[i-1] {
|
||||
continue
|
||||
}
|
||||
for j, k := i+1, n-1; j < k; {
|
||||
sum := nums[i] + nums[j] + nums[k]
|
||||
if abs(sum-target) < diff {
|
||||
|
@ -2,7 +2,92 @@ package leetcode
|
||||
|
||||
import "sort"
|
||||
|
||||
func fourSum(nums []int, target int) [][]int {
|
||||
// 解法一 双指针
|
||||
func fourSum(nums []int, target int) (quadruplets [][]int) {
|
||||
sort.Ints(nums)
|
||||
n := len(nums)
|
||||
for i := 0; i < n-3 && nums[i]+nums[i+1]+nums[i+2]+nums[i+3] <= target; i++ {
|
||||
if i > 0 && nums[i] == nums[i-1] || nums[i]+nums[n-3]+nums[n-2]+nums[n-1] < target {
|
||||
continue
|
||||
}
|
||||
for j := i + 1; j < n-2 && nums[i]+nums[j]+nums[j+1]+nums[j+2] <= target; j++ {
|
||||
if j > i+1 && nums[j] == nums[j-1] || nums[i]+nums[j]+nums[n-2]+nums[n-1] < target {
|
||||
continue
|
||||
}
|
||||
for left, right := j+1, n-1; left < right; {
|
||||
if sum := nums[i] + nums[j] + nums[left] + nums[right]; sum == target {
|
||||
quadruplets = append(quadruplets, []int{nums[i], nums[j], nums[left], nums[right]})
|
||||
for left++; left < right && nums[left] == nums[left-1]; left++ {
|
||||
}
|
||||
for right--; left < right && nums[right] == nums[right+1]; right-- {
|
||||
}
|
||||
} else if sum < target {
|
||||
left++
|
||||
} else {
|
||||
right--
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 解法二 kSum
|
||||
func fourSum1(nums []int, target int) [][]int {
|
||||
res, cur := make([][]int, 0), make([]int, 0)
|
||||
sort.Ints(nums)
|
||||
kSum(nums, 0, len(nums)-1, target, 4, cur, &res)
|
||||
return res
|
||||
}
|
||||
|
||||
func kSum(nums []int, left, right int, target int, k int, cur []int, res *[][]int) {
|
||||
if right-left+1 < k || k < 2 || target < nums[left]*k || target > nums[right]*k {
|
||||
return
|
||||
}
|
||||
if k == 2 {
|
||||
// 2 sum
|
||||
twoSum(nums, left, right, target, cur, res)
|
||||
} else {
|
||||
for i := left; i < len(nums); i++ {
|
||||
if i == left || (i > left && nums[i-1] != nums[i]) {
|
||||
next := make([]int, len(cur))
|
||||
copy(next, cur)
|
||||
next = append(next, nums[i])
|
||||
kSum(nums, i+1, len(nums)-1, target-nums[i], k-1, next, res)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func twoSum(nums []int, left, right int, target int, cur []int, res *[][]int) {
|
||||
for left < right {
|
||||
sum := nums[left] + nums[right]
|
||||
if sum == target {
|
||||
cur = append(cur, nums[left], nums[right])
|
||||
temp := make([]int, len(cur))
|
||||
copy(temp, cur)
|
||||
*res = append(*res, temp)
|
||||
// reset cur to previous state
|
||||
cur = cur[:len(cur)-2]
|
||||
left++
|
||||
right--
|
||||
for left < right && nums[left] == nums[left-1] {
|
||||
left++
|
||||
}
|
||||
for left < right && nums[right] == nums[right+1] {
|
||||
right--
|
||||
}
|
||||
} else if sum < target {
|
||||
left++
|
||||
} else {
|
||||
right--
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 解法三
|
||||
func fourSum2(nums []int, target int) [][]int {
|
||||
res := [][]int{}
|
||||
counter := map[int]int{}
|
||||
for _, value := range nums {
|
||||
|
@ -17,22 +17,18 @@ type ListNode = structures.ListNode
|
||||
|
||||
// 解法一
|
||||
func removeNthFromEnd(head *ListNode, n int) *ListNode {
|
||||
var fast, slow *ListNode
|
||||
fast = head
|
||||
slow = head
|
||||
for i := 0; i < n; i++ {
|
||||
dummyHead := &ListNode{Next: head}
|
||||
preSlow, slow, fast := dummyHead, head, head
|
||||
for fast != nil {
|
||||
if n <= 0 {
|
||||
preSlow = slow
|
||||
slow = slow.Next
|
||||
}
|
||||
n--
|
||||
fast = fast.Next
|
||||
}
|
||||
if fast == nil {
|
||||
head = head.Next
|
||||
return head
|
||||
}
|
||||
for fast.Next != nil {
|
||||
fast = fast.Next
|
||||
slow = slow.Next
|
||||
}
|
||||
slow.Next = slow.Next.Next
|
||||
return head
|
||||
preSlow.Next = slow.Next
|
||||
return dummyHead.Next
|
||||
}
|
||||
|
||||
// 解法二
|
||||
|
@ -29,6 +29,26 @@ func Test_Problem19(t *testing.T) {
|
||||
|
||||
qs := []question19{
|
||||
|
||||
{
|
||||
para19{[]int{1}, 3},
|
||||
ans19{[]int{1}},
|
||||
},
|
||||
|
||||
{
|
||||
para19{[]int{1, 2}, 2},
|
||||
ans19{[]int{2}},
|
||||
},
|
||||
|
||||
{
|
||||
para19{[]int{1}, 1},
|
||||
ans19{[]int{}},
|
||||
},
|
||||
|
||||
{
|
||||
para19{[]int{1, 2, 3, 4, 5}, 10},
|
||||
ans19{[]int{1, 2, 3, 4, 5}},
|
||||
},
|
||||
|
||||
{
|
||||
para19{[]int{1, 2, 3, 4, 5}, 1},
|
||||
ans19{[]int{1, 2, 3, 4}},
|
||||
|
@ -2,16 +2,44 @@
|
||||
|
||||
## 题目
|
||||
|
||||
Given a linked list, remove the n-th node from the end of list and return its head.
|
||||
Given the `head` of a linked list, remove the `nth` node from the end of the list and return its head.
|
||||
|
||||
Example:
|
||||
**Follow up:** Could you do this in one pass?
|
||||
|
||||
**Example 1:**
|
||||
|
||||

|
||||
|
||||
```
|
||||
Given linked list: 1->2->3->4->5, and n = 2.
|
||||
Input: head = [1,2,3,4,5], n = 2
|
||||
Output: [1,2,3,5]
|
||||
|
||||
After removing the second node from the end, the linked list becomes 1->2->3->5.
|
||||
```
|
||||
|
||||
**Example 2:**
|
||||
|
||||
```
|
||||
Input: head = [1], n = 1
|
||||
Output: []
|
||||
|
||||
```
|
||||
|
||||
**Example 3:**
|
||||
|
||||
```
|
||||
Input: head = [1,2], n = 1
|
||||
Output: [1]
|
||||
|
||||
```
|
||||
|
||||
**Constraints:**
|
||||
|
||||
- The number of nodes in the list is `sz`.
|
||||
- `1 <= sz <= 30`
|
||||
- `0 <= Node.val <= 100`
|
||||
- `1 <= n <= sz`
|
||||
|
||||
|
||||
## 题目大意
|
||||
|
||||
删除链表中倒数第 n 个结点。
|
||||
|
@ -16,30 +16,9 @@ type ListNode = structures.ListNode
|
||||
*/
|
||||
|
||||
func swapPairs(head *ListNode) *ListNode {
|
||||
if head == nil || head.Next == nil {
|
||||
return head
|
||||
dummy := &ListNode{Next: head}
|
||||
for pt := dummy; pt != nil && pt.Next != nil && pt.Next.Next != nil; {
|
||||
pt, pt.Next, pt.Next.Next, pt.Next.Next.Next = pt.Next, pt.Next.Next, pt.Next.Next.Next, pt.Next
|
||||
}
|
||||
s := head.Next
|
||||
var behind *ListNode
|
||||
for head.Next != nil {
|
||||
headNext := head.Next
|
||||
if behind != nil && behind.Next != nil {
|
||||
behind.Next = headNext
|
||||
}
|
||||
var next *ListNode
|
||||
if head.Next.Next != nil {
|
||||
next = head.Next.Next
|
||||
}
|
||||
if head.Next.Next != nil {
|
||||
head.Next = next
|
||||
} else {
|
||||
head.Next = nil
|
||||
}
|
||||
headNext.Next = head
|
||||
behind = head
|
||||
if head.Next != nil {
|
||||
head = next
|
||||
}
|
||||
}
|
||||
return s
|
||||
return dummy.Next
|
||||
}
|
||||
|
@ -0,0 +1,58 @@
|
||||
package leetcode
|
||||
|
||||
// 解法一 栈
|
||||
func longestValidParentheses(s string) int {
|
||||
stack, res := []int{}, 0
|
||||
stack = append(stack, -1)
|
||||
for i := 0; i < len(s); i++ {
|
||||
if s[i] == '(' {
|
||||
stack = append(stack, i)
|
||||
} else {
|
||||
stack = stack[:len(stack)-1]
|
||||
if len(stack) == 0 {
|
||||
stack = append(stack, i)
|
||||
} else {
|
||||
res = max(res, i-stack[len(stack)-1])
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func max(a, b int) int {
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// 解法二 双指针
|
||||
func longestValidParentheses1(s string) int {
|
||||
left, right, maxLength := 0, 0, 0
|
||||
for i := 0; i < len(s); i++ {
|
||||
if s[i] == '(' {
|
||||
left++
|
||||
} else {
|
||||
right++
|
||||
}
|
||||
if left == right {
|
||||
maxLength = max(maxLength, 2*right)
|
||||
} else if right > left {
|
||||
left, right = 0, 0
|
||||
}
|
||||
}
|
||||
left, right = 0, 0
|
||||
for i := len(s) - 1; i >= 0; i-- {
|
||||
if s[i] == '(' {
|
||||
left++
|
||||
} else {
|
||||
right++
|
||||
}
|
||||
if left == right {
|
||||
maxLength = max(maxLength, 2*left)
|
||||
} else if left > right {
|
||||
left, right = 0, 0
|
||||
}
|
||||
}
|
||||
return maxLength
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type question32 struct {
|
||||
para32
|
||||
ans32
|
||||
}
|
||||
|
||||
// para 是参数
|
||||
// one 代表第一个参数
|
||||
type para32 struct {
|
||||
s string
|
||||
}
|
||||
|
||||
// ans 是答案
|
||||
// one 代表第一个答案
|
||||
type ans32 struct {
|
||||
one int
|
||||
}
|
||||
|
||||
func Test_Problem32(t *testing.T) {
|
||||
|
||||
qs := []question32{
|
||||
|
||||
{
|
||||
para32{"(()"},
|
||||
ans32{2},
|
||||
},
|
||||
|
||||
{
|
||||
para32{")()())"},
|
||||
ans32{4},
|
||||
},
|
||||
|
||||
{
|
||||
para32{"()(())"},
|
||||
ans32{6},
|
||||
},
|
||||
|
||||
{
|
||||
para32{"()(())))"},
|
||||
ans32{6},
|
||||
},
|
||||
|
||||
{
|
||||
para32{"()(()"},
|
||||
ans32{2},
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Printf("------------------------Leetcode Problem 32------------------------\n")
|
||||
for _, q := range qs {
|
||||
_, p := q.ans32, q.para32
|
||||
fmt.Printf("【input】:%v 【output】:%v\n", p, longestValidParentheses(p.s))
|
||||
}
|
||||
fmt.Printf("\n\n\n")
|
||||
}
|
108
leetcode/0032.Longest-Valid-Parentheses/README.md
Normal file
108
leetcode/0032.Longest-Valid-Parentheses/README.md
Normal file
@ -0,0 +1,108 @@
|
||||
# [32. Longest Valid Parentheses](https://leetcode.com/problems/longest-valid-parentheses/)
|
||||
|
||||
|
||||
## 题目
|
||||
|
||||
Given a string containing just the characters `'('` and `')'`, find the length of the longest valid (well-formed) parentheses substring.
|
||||
|
||||
**Example 1:**
|
||||
|
||||
```
|
||||
Input: s = "(()"
|
||||
Output: 2
|
||||
Explanation: The longest valid parentheses substring is "()".
|
||||
```
|
||||
|
||||
**Example 2:**
|
||||
|
||||
```
|
||||
Input: s = ")()())"
|
||||
Output: 4
|
||||
Explanation: The longest valid parentheses substring is "()()".
|
||||
```
|
||||
|
||||
**Example 3:**
|
||||
|
||||
```
|
||||
Input: s = ""
|
||||
Output: 0
|
||||
```
|
||||
|
||||
**Constraints:**
|
||||
|
||||
- `0 <= s.length <= 3 * 104`
|
||||
- `s[i]` is `'('`, or `')'`.
|
||||
|
||||
## 题目大意
|
||||
|
||||
给你一个只包含 '(' 和 ')' 的字符串,找出最长有效(格式正确且连续)括号子串的长度。
|
||||
|
||||
## 解题思路
|
||||
|
||||
- 提到括号匹配,第一时间能让人想到的就是利用栈。这里需要计算嵌套括号的总长度,所以栈里面不能单纯的存左括号,而应该存左括号在原字符串的下标,这样通过下标相减可以获取长度。那么栈如果是非空,栈底永远存的是当前遍历过的字符串中**上一个没有被匹配的右括号的下标**。**上一个没有被匹配的右括号的下标**可以理解为每段括号匹配之间的“隔板”。例如,`())((()))`,第三个右括号,即为左右 2 段正确的括号匹配中间的“隔板”。“隔板”的存在影响计算最长括号长度。如果不存在“隔板”,前后 2 段正确的括号匹配应该“融合”在一起,最长长度为 `2 + 6 = 8`,但是这里存在了“隔板”,所以最长长度仅为 `6`。
|
||||
- 具体算法实现,遇到每个 `'('` ,将它的下标压入栈中。对于遇到的每个 `')'`,先弹出栈顶元素表示匹配了当前右括号。如果栈为空,说明当前的右括号为没有被匹配的右括号,于是将其下标放入栈中来更新**上一个没有被匹配的右括号的下标**。如果栈不为空,当前右括号的下标减去栈顶元素即为以该右括号为结尾的最长有效括号的长度。需要注意初始化时,不存在**上一个没有被匹配的右括号的下标**,那么将 `-1` 放入栈中,充当下标为 `0` 的“隔板”。时间复杂度 O(n),空间复杂度 O(n)。
|
||||
- 在栈的方法中,实际用到的元素仅仅是栈底的**上一个没有被匹配的右括号的下标**。那么考虑能否把这个值存在一个变量中,这样可以省去栈 O(n) 的时间复杂度。利用两个计数器 left 和 right 。首先,从左到右遍历字符串,每当遇到 `'('`,增加 left 计数器,每当遇到 `')'` ,增加 right 计数器。每当 left 计数器与 right 计数器相等时,计算当前有效字符串的长度,并且记录目前为止找到的最长子字符串。当 right 计数器比 left 计数器大时,说明括号不匹配,于是将 left 和 right 计数器同时变回 0。这样的做法利用了贪心的思想,考虑了以当前字符下标结尾的有效括号长度,每次当右括号数量多于左括号数量的时候之前的字符就扔掉不再考虑,重新从下一个字符开始计算。
|
||||
- 但上面的做法会漏掉一种情况,就是遍历的时候左括号的数量始终大于右括号的数量,即 `(()` ,这种时候最长有效括号是求不出来的。解决办法是反向再计算一遍,如果从右往左计算,`(()` 先计算匹配的括号,最后只剩下 `'('`,这样依旧可以算出最长匹配的括号长度。反过来计算的方法和上述从左往右计算的方法一致:当 left 计数器比 right 计数器大时,将 left 和 right 计数器同时变回 0;当 left 计数器与 right 计数器相等时,计算当前有效字符串的长度,并且记录目前为止找到的最长子字符串。这种方法的时间复杂度是 O(n),空间复杂度 O(1)。
|
||||
|
||||
## 代码
|
||||
|
||||
```go
|
||||
package leetcode
|
||||
|
||||
// 解法一 栈
|
||||
func longestValidParentheses(s string) int {
|
||||
stack, res := []int{}, 0
|
||||
stack = append(stack, -1)
|
||||
for i := 0; i < len(s); i++ {
|
||||
if s[i] == '(' {
|
||||
stack = append(stack, i)
|
||||
} else {
|
||||
stack = stack[:len(stack)-1]
|
||||
if len(stack) == 0 {
|
||||
stack = append(stack, i)
|
||||
} else {
|
||||
res = max(res, i-stack[len(stack)-1])
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func max(a, b int) int {
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// 解法二 双指针
|
||||
func longestValidParentheses1(s string) int {
|
||||
left, right, maxLength := 0, 0, 0
|
||||
for i := 0; i < len(s); i++ {
|
||||
if s[i] == '(' {
|
||||
left++
|
||||
} else {
|
||||
right++
|
||||
}
|
||||
if left == right {
|
||||
maxLength = max(maxLength, 2*right)
|
||||
} else if right > left {
|
||||
left, right = 0, 0
|
||||
}
|
||||
}
|
||||
left, right = 0, 0
|
||||
for i := len(s) - 1; i >= 0; i-- {
|
||||
if s[i] == '(' {
|
||||
left++
|
||||
} else {
|
||||
right++
|
||||
}
|
||||
if left == right {
|
||||
maxLength = max(maxLength, 2*left)
|
||||
} else if left > right {
|
||||
left, right = 0, 0
|
||||
}
|
||||
}
|
||||
return maxLength
|
||||
}
|
||||
```
|
25
leetcode/0043.Multiply-Strings/43. Multiply Strings.go
Normal file
25
leetcode/0043.Multiply-Strings/43. Multiply Strings.go
Normal file
@ -0,0 +1,25 @@
|
||||
package leetcode
|
||||
|
||||
func multiply(num1 string, num2 string) string {
|
||||
if num1 == "0" || num2 == "0" {
|
||||
return "0"
|
||||
}
|
||||
b1, b2, tmp := []byte(num1), []byte(num2), make([]int, len(num1)+len(num2))
|
||||
for i := 0; i < len(b1); i++ {
|
||||
for j := 0; j < len(b2); j++ {
|
||||
tmp[i+j+1] += int(b1[i]-'0') * int(b2[j]-'0')
|
||||
}
|
||||
}
|
||||
for i := len(tmp) - 1; i > 0; i-- {
|
||||
tmp[i-1] += tmp[i] / 10
|
||||
tmp[i] = tmp[i] % 10
|
||||
}
|
||||
if tmp[0] == 0 {
|
||||
tmp = tmp[1:]
|
||||
}
|
||||
res := make([]byte, len(tmp))
|
||||
for i := 0; i < len(tmp); i++ {
|
||||
res[i] = '0' + byte(tmp[i])
|
||||
}
|
||||
return string(res)
|
||||
}
|
48
leetcode/0043.Multiply-Strings/43. Multiply Strings_test.go
Normal file
48
leetcode/0043.Multiply-Strings/43. Multiply Strings_test.go
Normal file
@ -0,0 +1,48 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type question43 struct {
|
||||
para43
|
||||
ans43
|
||||
}
|
||||
|
||||
// para 是参数
|
||||
// one 代表第一个参数
|
||||
type para43 struct {
|
||||
num1 string
|
||||
num2 string
|
||||
}
|
||||
|
||||
// ans 是答案
|
||||
// one 代表第一个答案
|
||||
type ans43 struct {
|
||||
one string
|
||||
}
|
||||
|
||||
func Test_Problem43(t *testing.T) {
|
||||
|
||||
qs := []question43{
|
||||
|
||||
{
|
||||
para43{"2", "3"},
|
||||
ans43{"6"},
|
||||
},
|
||||
|
||||
{
|
||||
para43{"123", "456"},
|
||||
ans43{"56088"},
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Printf("------------------------Leetcode Problem 43------------------------\n")
|
||||
|
||||
for _, q := range qs {
|
||||
_, p := q.ans43, q.para43
|
||||
fmt.Printf("【input】:%v 【output】:%v\n", p, multiply(p.num1, p.num2))
|
||||
}
|
||||
fmt.Printf("\n\n\n")
|
||||
}
|
66
leetcode/0043.Multiply-Strings/README.md
Normal file
66
leetcode/0043.Multiply-Strings/README.md
Normal file
@ -0,0 +1,66 @@
|
||||
# [43. Multiply Strings](https://leetcode.com/problems/multiply-strings/)
|
||||
|
||||
|
||||
## 题目
|
||||
|
||||
Given two non-negative integers `num1` and `num2` represented as strings, return the product of `num1` and `num2`, also represented as a string.
|
||||
|
||||
**Note:** You must not use any built-in BigInteger library or convert the inputs to integer directly.
|
||||
|
||||
**Example 1:**
|
||||
|
||||
```
|
||||
Input: num1 = "2", num2 = "3"
|
||||
Output: "6"
|
||||
```
|
||||
|
||||
**Example 2:**
|
||||
|
||||
```
|
||||
Input: num1 = "123", num2 = "456"
|
||||
Output: "56088"
|
||||
```
|
||||
|
||||
**Constraints:**
|
||||
|
||||
- `1 <= num1.length, num2.length <= 200`
|
||||
- `num1` and `num2` consist of digits only.
|
||||
- Both `num1` and `num2` do not contain any leading zero, except the number `0` itself.
|
||||
|
||||
## 题目大意
|
||||
|
||||
给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。
|
||||
|
||||
## 解题思路
|
||||
|
||||
- 用数组模拟乘法。创建一个数组长度为 `len(num1) + len(num2)` 的数组用于存储乘积。对于任意 `0 ≤ i < len(num1)`,`0 ≤ j < len(num2)`,`num1[i] * num2[j]` 的结果位于 `tmp[i+j+1]`,如果 `tmp[i+j+1]≥10`,则将进位部分加到 `tmp[i+j]`。最后,将数组 `tmp` 转成字符串,如果最高位是 0 则舍弃最高位。
|
||||
|
||||
## 代码
|
||||
|
||||
```go
|
||||
package leetcode
|
||||
|
||||
func multiply(num1 string, num2 string) string {
|
||||
if num1 == "0" || num2 == "0" {
|
||||
return "0"
|
||||
}
|
||||
b1, b2, tmp := []byte(num1), []byte(num2), make([]int, len(num1)+len(num2))
|
||||
for i := 0; i < len(b1); i++ {
|
||||
for j := 0; j < len(b2); j++ {
|
||||
tmp[i+j+1] += int(b1[i]-'0') * int(b2[j]-'0')
|
||||
}
|
||||
}
|
||||
for i := len(tmp) - 1; i > 0; i-- {
|
||||
tmp[i-1] += tmp[i] / 10
|
||||
tmp[i] = tmp[i] % 10
|
||||
}
|
||||
if tmp[0] == 0 {
|
||||
tmp = tmp[1:]
|
||||
}
|
||||
res := make([]byte, len(tmp))
|
||||
for i := 0; i < len(tmp); i++ {
|
||||
res[i] = '0' + byte(tmp[i])
|
||||
}
|
||||
return string(res)
|
||||
}
|
||||
```
|
21
leetcode/0045.Jump-Game-II/45. Jump Game II.go
Normal file
21
leetcode/0045.Jump-Game-II/45. Jump Game II.go
Normal file
@ -0,0 +1,21 @@
|
||||
package leetcode
|
||||
|
||||
func jump(nums []int) int {
|
||||
if len(nums) == 1 {
|
||||
return 0
|
||||
}
|
||||
needChoose, canReach, step := 0, 0, 0
|
||||
for i, x := range nums {
|
||||
if i+x > canReach {
|
||||
canReach = i + x
|
||||
if canReach >= len(nums)-1 {
|
||||
return step + 1
|
||||
}
|
||||
}
|
||||
if i == needChoose {
|
||||
needChoose = canReach
|
||||
step++
|
||||
}
|
||||
}
|
||||
return step
|
||||
}
|
47
leetcode/0045.Jump-Game-II/45. Jump Game II_test.go
Normal file
47
leetcode/0045.Jump-Game-II/45. Jump Game II_test.go
Normal file
@ -0,0 +1,47 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type question45 struct {
|
||||
para45
|
||||
ans45
|
||||
}
|
||||
|
||||
// para 是参数
|
||||
// one 代表第一个参数
|
||||
type para45 struct {
|
||||
nums []int
|
||||
}
|
||||
|
||||
// ans 是答案
|
||||
// one 代表第一个答案
|
||||
type ans45 struct {
|
||||
one int
|
||||
}
|
||||
|
||||
func Test_Problem45(t *testing.T) {
|
||||
|
||||
qs := []question45{
|
||||
|
||||
{
|
||||
para45{[]int{2, 3, 1, 1, 4}},
|
||||
ans45{2},
|
||||
},
|
||||
|
||||
{
|
||||
para45{[]int{2, 3, 0, 1, 4}},
|
||||
ans45{2},
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Printf("------------------------Leetcode Problem 45------------------------\n")
|
||||
|
||||
for _, q := range qs {
|
||||
_, p := q.ans45, q.para45
|
||||
fmt.Printf("【input】:%v 【output】:%v\n", p, jump(p.nums))
|
||||
}
|
||||
fmt.Printf("\n\n\n")
|
||||
}
|
67
leetcode/0045.Jump-Game-II/README.md
Normal file
67
leetcode/0045.Jump-Game-II/README.md
Normal file
@ -0,0 +1,67 @@
|
||||
# [45. Jump Game II](https://leetcode.com/problems/jump-game-ii/)
|
||||
|
||||
|
||||
## 题目
|
||||
|
||||
Given an array of non-negative integers `nums`, you are initially positioned at the first index of the array.
|
||||
|
||||
Each element in the array represents your maximum jump length at that position.
|
||||
|
||||
Your goal is to reach the last index in the minimum number of jumps.
|
||||
|
||||
You can assume that you can always reach the last index.
|
||||
|
||||
**Example 1:**
|
||||
|
||||
```
|
||||
Input: nums = [2,3,1,1,4]
|
||||
Output: 2
|
||||
Explanation: The minimum number of jumps to reach the last index is 2. Jump 1 step from index 0 to 1, then 3 steps to the last index.
|
||||
```
|
||||
|
||||
**Example 2:**
|
||||
|
||||
```
|
||||
Input: nums = [2,3,0,1,4]
|
||||
Output: 2
|
||||
```
|
||||
|
||||
**Constraints:**
|
||||
|
||||
- `1 <= nums.length <= 1000`
|
||||
- `0 <= nums[i] <= 10^5`
|
||||
|
||||
## 题目大意
|
||||
|
||||
给定一个非负整数数组,你最初位于数组的第一个位置。数组中的每个元素代表你在该位置可以跳跃的最大长度。你的目标是使用最少的跳跃次数到达数组的最后一个位置。
|
||||
|
||||
## 解题思路
|
||||
|
||||
- 要求找到最少跳跃次数,顺理成章的会想到用贪心算法解题。扫描步数数组,维护当前能够到达最大下标的位置,记为能到达的最远边界,如果扫描过程中到达了最远边界,更新边界并将跳跃次数 + 1。
|
||||
- 扫描数组的时候,其实不需要扫描最后一个元素,因为在跳到最后一个元素之前,能到达的最远边界一定大于等于最后一个元素的位置,不然就跳不到最后一个元素,到达不了终点了;如果遍历到最后一个元素,说明边界正好为最后一个位置,最终跳跃次数直接 + 1 即可,也不需要访问最后一个元素。
|
||||
|
||||
## 代码
|
||||
|
||||
```go
|
||||
package leetcode
|
||||
|
||||
func jump(nums []int) int {
|
||||
if len(nums) == 1 {
|
||||
return 0
|
||||
}
|
||||
needChoose, canReach, step := 0, 0, 0
|
||||
for i, x := range nums {
|
||||
if i+x > canReach {
|
||||
canReach = i + x
|
||||
if canReach >= len(nums)-1 {
|
||||
return step + 1
|
||||
}
|
||||
}
|
||||
if i == needChoose {
|
||||
needChoose = canReach
|
||||
step++
|
||||
}
|
||||
}
|
||||
return step
|
||||
}
|
||||
```
|
@ -1,26 +1,17 @@
|
||||
package leetcode
|
||||
|
||||
func rotate(matrix [][]int) {
|
||||
row := len(matrix)
|
||||
if row <= 0 {
|
||||
return
|
||||
}
|
||||
column := len(matrix[0])
|
||||
length := len(matrix)
|
||||
// rotate by diagonal 对角线变换
|
||||
for i := 0; i < row; i++ {
|
||||
for j := i + 1; j < column; j++ {
|
||||
tmp := matrix[i][j]
|
||||
matrix[i][j] = matrix[j][i]
|
||||
matrix[j][i] = tmp
|
||||
for i := 0; i < length; i++ {
|
||||
for j := i + 1; j < length; j++ {
|
||||
matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]
|
||||
}
|
||||
}
|
||||
// rotate by vertical centerline 竖直轴对称翻转
|
||||
halfColumn := column / 2
|
||||
for i := 0; i < row; i++ {
|
||||
for j := 0; j < halfColumn; j++ {
|
||||
tmp := matrix[i][j]
|
||||
matrix[i][j] = matrix[i][column-j-1]
|
||||
matrix[i][column-j-1] = tmp
|
||||
for i := 0; i < length; i++ {
|
||||
for j := 0; j < length/2; j++ {
|
||||
matrix[i][j], matrix[i][length-j-1] = matrix[i][length-j-1], matrix[i][j]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,8 +10,9 @@ Rotate the image by 90 degrees (clockwise).
|
||||
|
||||
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.
|
||||
|
||||
**Example 1:**
|
||||
**Example 1**:
|
||||
|
||||

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

|
||||
|
||||
Given input matrix =
|
||||
[
|
||||
|
@ -47,39 +47,45 @@ func generateBoard(n int, row *[]int) []string {
|
||||
return board
|
||||
}
|
||||
|
||||
// 解法二 二进制操作法
|
||||
// class Solution
|
||||
// {
|
||||
// int n;
|
||||
// string getNq(int p)
|
||||
// {
|
||||
// string s(n, '.');
|
||||
// s[p] = 'Q';
|
||||
// return s;
|
||||
// }
|
||||
// void nQueens(int p, int l, int m, int r, vector<vector<string>> &res)
|
||||
// {
|
||||
// static vector<string> ans;
|
||||
// if (p >= n)
|
||||
// {
|
||||
// res.push_back(ans);
|
||||
// return ;
|
||||
// }
|
||||
// int mask = l | m | r;
|
||||
// for (int i = 0, b = 1; i < n; ++ i, b <<= 1)
|
||||
// if (!(mask & b))
|
||||
// {
|
||||
// ans.push_back(getNq(i));
|
||||
// nQueens(p + 1, (l | b) >> 1, m | b, (r | b) << 1, res);
|
||||
// ans.pop_back();
|
||||
// }
|
||||
// }
|
||||
// public:
|
||||
// vector<vector<string> > solveNQueens(int n)
|
||||
// {
|
||||
// this->n = n;
|
||||
// vector<vector<string>> res;
|
||||
// nQueens(0, 0, 0, 0, res);
|
||||
// return res;
|
||||
// }
|
||||
// };
|
||||
// 解法二 二进制操作法 Signed-off-by: Hanlin Shi shihanlin9@gmail.com
|
||||
func solveNQueens2(n int) (res [][]string) {
|
||||
placements := make([]string, n)
|
||||
for i := range placements {
|
||||
buf := make([]byte, n)
|
||||
for j := range placements {
|
||||
if i == j {
|
||||
buf[j] = 'Q'
|
||||
} else {
|
||||
buf[j] = '.'
|
||||
}
|
||||
}
|
||||
placements[i] = string(buf)
|
||||
}
|
||||
var construct func(prev []int)
|
||||
construct = func(prev []int) {
|
||||
if len(prev) == n {
|
||||
plan := make([]string, n)
|
||||
for i := 0; i < n; i++ {
|
||||
plan[i] = placements[prev[i]]
|
||||
}
|
||||
res = append(res, plan)
|
||||
return
|
||||
}
|
||||
occupied := 0
|
||||
for i := range prev {
|
||||
dist := len(prev) - i
|
||||
bit := 1 << prev[i]
|
||||
occupied |= bit | bit<<dist | bit>>dist
|
||||
}
|
||||
prev = append(prev, -1)
|
||||
for i := 0; i < n; i++ {
|
||||
if (occupied>>i)&1 != 0 {
|
||||
continue
|
||||
}
|
||||
prev[len(prev)-1] = i
|
||||
construct(prev)
|
||||
}
|
||||
}
|
||||
construct(make([]int, 0, n))
|
||||
return
|
||||
}
|
||||
|
@ -40,4 +40,5 @@ Each solution contains a distinct board configuration of the *n*-queens' placem
|
||||
- 利用 col 数组记录列信息,col 有 `n` 列。用 dia1,dia2 记录从左下到右上的对角线,从左上到右下的对角线的信息,dia1 和 dia2 分别都有 `2*n-1` 个。
|
||||
- dia1 对角线的规律是 `i + j 是定值`,例如[0,0],为 0;[1,0]、[0,1] 为 1;[2,0]、[1,1]、[0,2] 为 2;
|
||||
- dia2 对角线的规律是 `i - j 是定值`,例如[0,7],为 -7;[0,6]、[1,7] 为 -6;[0,5]、[1,6]、[2,7] 为 -5;为了使他们从 0 开始,i - j + n - 1 偏移到 0 开始,所以 dia2 的规律是 `i - j + n - 1 为定值`。
|
||||
- 还有一个位运算的方法,每行只能选一个位置放皇后,那么对每行遍历可能放皇后的位置。如何高效判断哪些点不能放皇后呢?这里的做法毕竟巧妙,把所有之前选过的点按照顺序存下来,然后根据之前选的点到当前行的距离,就可以快速判断是不是会有冲突。举个例子: 假如在 4 皇后问题中,如果第一二行已经选择了位置 [1, 3],那么在第三行选择时,首先不能再选 1, 3 列了,而对于第三行, 1 距离长度为2,所以它会影响到 -1, 3 两个列。同理,3 在第二行,距离第三行为 1,所以 3 会影响到列 2, 4。由上面的结果,我们知道 -1, 4 超出边界了不用去管,别的不能选的点是 1, 2, 3,所以第三行就只能选 0。在代码实现中,可以在每次遍历前根据之前选择的情况生成一个 occupied 用来记录当前这一行,已经被选了的和由于之前皇后攻击范围所以不能选的位置,然后只选择合法的位置进入到下一层递归。另外就是预处理了一个皇后放不同位置的字符串,这样这些字符串在返回结果的时候是可以在内存中复用的,省一点内存。
|
||||
|
||||
|
16
leetcode/0058.Length-of-Last-Word/58.Length of Last Word.go
Normal file
16
leetcode/0058.Length-of-Last-Word/58.Length of Last Word.go
Normal file
@ -0,0 +1,16 @@
|
||||
package leetcode
|
||||
|
||||
func lengthOfLastWord(s string) int {
|
||||
last := len(s) - 1
|
||||
for last >= 0 && s[last] == ' ' {
|
||||
last--
|
||||
}
|
||||
if last < 0 {
|
||||
return 0
|
||||
}
|
||||
first := last
|
||||
for first >= 0 && s[first] != ' ' {
|
||||
first--
|
||||
}
|
||||
return last - first
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type question58 struct {
|
||||
para58
|
||||
ans58
|
||||
}
|
||||
|
||||
// para 是参数
|
||||
type para58 struct {
|
||||
s string
|
||||
}
|
||||
|
||||
// ans 是答案
|
||||
type ans58 struct {
|
||||
ans int
|
||||
}
|
||||
|
||||
func Test_Problem58(t *testing.T) {
|
||||
|
||||
qs := []question58{
|
||||
|
||||
{
|
||||
para58{"Hello World"},
|
||||
ans58{5},
|
||||
},
|
||||
|
||||
{
|
||||
para58{" fly me to the moon "},
|
||||
ans58{4},
|
||||
},
|
||||
|
||||
{
|
||||
para58{"luffy is still joyboy"},
|
||||
ans58{6},
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Printf("------------------------Leetcode Problem 58------------------------\n")
|
||||
|
||||
for _, q := range qs {
|
||||
_, p := q.ans58, q.para58
|
||||
fmt.Printf("【input】:%v 【output】:%v\n", p, lengthOfLastWord(p.s))
|
||||
}
|
||||
fmt.Printf("\n\n\n")
|
||||
}
|
70
leetcode/0058.Length-of-Last-Word/README.md
Normal file
70
leetcode/0058.Length-of-Last-Word/README.md
Normal file
@ -0,0 +1,70 @@
|
||||
# [58. Length of Last Word](https://leetcode.com/problems/length-of-last-word/)
|
||||
|
||||
|
||||
## 题目
|
||||
|
||||
Given a string `s` consisting of some words separated by some number of spaces, return *the length of the **last** word in the string.*
|
||||
|
||||
A **word** is a maximal substring consisting of non-space characters only.
|
||||
|
||||
**Example 1:**
|
||||
|
||||
```
|
||||
Input: s = "Hello World"
|
||||
Output: 5
|
||||
Explanation: The last word is "World" with length 5.
|
||||
|
||||
```
|
||||
|
||||
**Example 2:**
|
||||
|
||||
```
|
||||
Input: s = " fly me to the moon "
|
||||
Output: 4
|
||||
Explanation: The last word is "moon" with length 4.
|
||||
|
||||
```
|
||||
|
||||
**Example 3:**
|
||||
|
||||
```
|
||||
Input: s = "luffy is still joyboy"
|
||||
Output: 6
|
||||
Explanation: The last word is "joyboy" with length 6.
|
||||
|
||||
```
|
||||
|
||||
**Constraints:**
|
||||
|
||||
- `1 <= s.length <= 104`
|
||||
- `s` consists of only English letters and spaces `' '`.
|
||||
- There will be at least one word in `s`.
|
||||
|
||||
## 题目大意
|
||||
|
||||
给你一个字符串 `s`,由若干单词组成,单词前后用一些空格字符隔开。返回字符串中最后一个单词的长度。**单词** 是指仅由字母组成、不包含任何空格字符的最大子字符串。
|
||||
|
||||
## 解题思路
|
||||
|
||||
- 先从后过滤掉空格找到单词尾部,再从尾部向前遍历,找到单词头部,最后两者相减,即为单词的长度。
|
||||
|
||||
## 代码
|
||||
|
||||
```go
|
||||
package leetcode
|
||||
|
||||
func lengthOfLastWord(s string) int {
|
||||
last := len(s) - 1
|
||||
for last >= 0 && s[last] == ' ' {
|
||||
last--
|
||||
}
|
||||
if last < 0 {
|
||||
return 0
|
||||
}
|
||||
first := last
|
||||
for first >= 0 && s[first] != ' ' {
|
||||
first--
|
||||
}
|
||||
return last - first
|
||||
}
|
||||
```
|
@ -5,14 +5,12 @@ func uniquePaths(m int, n int) int {
|
||||
for i := 0; i < n; i++ {
|
||||
dp[i] = make([]int, m)
|
||||
}
|
||||
for i := 0; i < m; i++ {
|
||||
dp[0][i] = 1
|
||||
}
|
||||
for i := 0; i < n; i++ {
|
||||
dp[i][0] = 1
|
||||
}
|
||||
for i := 1; i < n; i++ {
|
||||
for j := 1; j < m; j++ {
|
||||
for j := 0; j < m; j++ {
|
||||
if i == 0 || j == 0 {
|
||||
dp[i][j] = 1
|
||||
continue
|
||||
}
|
||||
dp[i][j] = dp[i-1][j] + dp[i][j-1]
|
||||
}
|
||||
}
|
||||
|
22
leetcode/0065.Valid-Number/65. Valid Number.go
Normal file
22
leetcode/0065.Valid-Number/65. Valid Number.go
Normal file
@ -0,0 +1,22 @@
|
||||
package leetcode
|
||||
|
||||
func isNumber(s string) bool {
|
||||
numFlag, dotFlag, eFlag := false, false, false
|
||||
for i := 0; i < len(s); i++ {
|
||||
if '0' <= s[i] && s[i] <= '9' {
|
||||
numFlag = true
|
||||
} else if s[i] == '.' && !dotFlag && !eFlag {
|
||||
dotFlag = true
|
||||
} else if (s[i] == 'e' || s[i] == 'E') && !eFlag && numFlag {
|
||||
eFlag = true
|
||||
numFlag = false // reJudge integer after 'e' or 'E'
|
||||
} else if (s[i] == '+' || s[i] == '-') && (i == 0 || s[i-1] == 'e' || s[i-1] == 'E') {
|
||||
continue
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
// avoid case: s == '.' or 'e/E' or '+/-' and etc...
|
||||
// string s must have num
|
||||
return numFlag
|
||||
}
|
41
leetcode/0065.Valid-Number/65. Valid Number_test.go
Normal file
41
leetcode/0065.Valid-Number/65. Valid Number_test.go
Normal file
@ -0,0 +1,41 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_Problem65(t *testing.T) {
|
||||
|
||||
tcs := []struct {
|
||||
s string
|
||||
ans bool
|
||||
}{
|
||||
|
||||
{
|
||||
"0",
|
||||
true,
|
||||
},
|
||||
|
||||
{
|
||||
"e",
|
||||
false,
|
||||
},
|
||||
|
||||
{
|
||||
".",
|
||||
false,
|
||||
},
|
||||
|
||||
{
|
||||
".1",
|
||||
true,
|
||||
},
|
||||
}
|
||||
fmt.Printf("------------------------Leetcode Problem 65------------------------\n")
|
||||
|
||||
for _, tc := range tcs {
|
||||
fmt.Printf("【input】:%v 【output】:%v\n", tc, isNumber(tc.s))
|
||||
}
|
||||
fmt.Printf("\n\n\n")
|
||||
}
|
78
leetcode/0065.Valid-Number/README.md
Normal file
78
leetcode/0065.Valid-Number/README.md
Normal file
@ -0,0 +1,78 @@
|
||||
# [65. Valid Number](https://leetcode.com/problems/valid-number/)
|
||||
|
||||
|
||||
## 题目
|
||||
|
||||
A **valid number** can be split up into these components (in order):
|
||||
|
||||
1. A **decimal number** or an integer.
|
||||
2. (Optional) An 'e' or 'E', followed by an **integer.**
|
||||
|
||||
A **decimal number** can be split up into these components (in order):
|
||||
|
||||
1. (Optional) A sign character (either '+' or '-').
|
||||
2. One of the following formats:
|
||||
1. One or more digits, followed by a dot '.'.
|
||||
2. One or more digits, followed by a dot '.', followed by one or more digits.
|
||||
3. A dot '.', followed by one or more digits.
|
||||
|
||||
An **integer** can be split up into these components (in order):
|
||||
|
||||
1. (Optional) A sign character (either '+' or '-').
|
||||
2. One or more digits.
|
||||
|
||||
For example, all the following are valid numbers: `["2", "0089", "-0.1", "+3.14", "4.", "-.9", "2e10", "-90E3", "3e+7", "+6e-1", "53.5e93", "-123.456e789"]`, while the following are not valid numbers: `["abc", "1a", "1e", "e3", "99e2.5", "--6", "-+3", "95a54e53"].`
|
||||
|
||||
Given a string s, return true if s is a **valid number.**
|
||||
|
||||
**Example:**
|
||||
|
||||
Input: s = "0"
|
||||
Output: true
|
||||
|
||||
Input: s = "e"
|
||||
Output: false
|
||||
|
||||
## 题目大意
|
||||
|
||||
给定一个字符串S,请根据以上的规则判断该字符串是否是一个有效的数字字符串。
|
||||
|
||||
|
||||
## 解题思路
|
||||
|
||||
- 用三个变量分别标记是否出现过数字、是否出现过'.'和 是否出现过 'e/E'
|
||||
- 从左到右依次遍历字符串中的每一个元素
|
||||
- 如果是数字,则标记数字出现过
|
||||
- 如果是 '.', 则需要 '.'没有出现过,并且 'e/E' 没有出现过,才会进行标记
|
||||
- 如果是 'e/E', 则需要 'e/E'没有出现过,并且前面出现过数字,才会进行标记
|
||||
- 如果是 '+/-', 则需要是第一个字符,或者前一个字符是 'e/E',才会进行标记,并重置数字出现的标识
|
||||
- 最后返回时,需要字符串中至少出现过数字,避免下列case: s == '.' or 'e/E' or '+/e' and etc...
|
||||
|
||||
## 代码
|
||||
|
||||
```go
|
||||
|
||||
package leetcode
|
||||
|
||||
func isNumber(s string) bool {
|
||||
numFlag, dotFlag, eFlag := false, false, false
|
||||
for i := 0; i < len(s); i++ {
|
||||
if '0' <= s[i] && s[i] <= '9' {
|
||||
numFlag = true
|
||||
} else if s[i] == '.' && !dotFlag && !eFlag {
|
||||
dotFlag = true
|
||||
} else if (s[i] == 'e' || s[i] == 'E') && !eFlag && numFlag {
|
||||
eFlag = true
|
||||
numFlag = false // reJudge integer after 'e' or 'E'
|
||||
} else if (s[i] == '+' || s[i] == '-') && (i == 0 || s[i-1] == 'e' || s[i-1] == 'E') {
|
||||
continue
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
// avoid case: s == '.' or 'e/E' or '+/-' and etc...
|
||||
// string s must have num
|
||||
return numFlag
|
||||
}
|
||||
|
||||
```
|
@ -1,21 +1,17 @@
|
||||
package leetcode
|
||||
|
||||
func plusOne(digits []int) []int {
|
||||
if len(digits) == 0 {
|
||||
return []int{}
|
||||
}
|
||||
carry := 1
|
||||
for i := len(digits) - 1; i >= 0; i-- {
|
||||
if digits[i]+carry > 9 {
|
||||
digits[i] = 0
|
||||
carry = 1
|
||||
} else {
|
||||
digits[i] += carry
|
||||
carry = 0
|
||||
digits[i]++
|
||||
if digits[i] != 10 {
|
||||
// no carry
|
||||
return digits
|
||||
}
|
||||
// carry
|
||||
digits[i] = 0
|
||||
}
|
||||
if digits[0] == 0 && carry == 1 {
|
||||
digits = append([]int{1}, digits...)
|
||||
}
|
||||
// all carry
|
||||
digits[0] = 1
|
||||
digits = append(digits, 0)
|
||||
return digits
|
||||
}
|
||||
|
@ -1,23 +1,17 @@
|
||||
package leetcode
|
||||
|
||||
// 解法一 二分
|
||||
// 解法一 二分, 找到最后一个满足 n^2 <= x 的整数n
|
||||
func mySqrt(x int) int {
|
||||
if x == 0 {
|
||||
return 0
|
||||
}
|
||||
left, right, res := 1, x, 0
|
||||
for left <= right {
|
||||
mid := left + ((right - left) >> 1)
|
||||
if mid < x/mid {
|
||||
left = mid + 1
|
||||
res = mid
|
||||
} else if mid == x/mid {
|
||||
return mid
|
||||
l, r := 0, x
|
||||
for l < r {
|
||||
mid := (l + r + 1) / 2
|
||||
if mid*mid > x {
|
||||
r = mid - 1
|
||||
} else {
|
||||
right = mid - 1
|
||||
l = mid
|
||||
}
|
||||
}
|
||||
return res
|
||||
return l
|
||||
}
|
||||
|
||||
// 解法二 牛顿迭代法 https://en.wikipedia.org/wiki/Integer_square_root
|
||||
|
54
leetcode/0073.Set-Matrix-Zeroes/73. Set Matrix Zeroes.go
Normal file
54
leetcode/0073.Set-Matrix-Zeroes/73. Set Matrix Zeroes.go
Normal file
@ -0,0 +1,54 @@
|
||||
package leetcode
|
||||
|
||||
func setZeroes(matrix [][]int) {
|
||||
if len(matrix) == 0 || len(matrix[0]) == 0 {
|
||||
return
|
||||
}
|
||||
isFirstRowExistZero, isFirstColExistZero := false, false
|
||||
for i := 0; i < len(matrix); i++ {
|
||||
if matrix[i][0] == 0 {
|
||||
isFirstColExistZero = true
|
||||
break
|
||||
}
|
||||
}
|
||||
for j := 0; j < len(matrix[0]); j++ {
|
||||
if matrix[0][j] == 0 {
|
||||
isFirstRowExistZero = true
|
||||
break
|
||||
}
|
||||
}
|
||||
for i := 1; i < len(matrix); i++ {
|
||||
for j := 1; j < len(matrix[0]); j++ {
|
||||
if matrix[i][j] == 0 {
|
||||
matrix[i][0] = 0
|
||||
matrix[0][j] = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
// 处理[1:]行全部置 0
|
||||
for i := 1; i < len(matrix); i++ {
|
||||
if matrix[i][0] == 0 {
|
||||
for j := 1; j < len(matrix[0]); j++ {
|
||||
matrix[i][j] = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
// 处理[1:]列全部置 0
|
||||
for j := 1; j < len(matrix[0]); j++ {
|
||||
if matrix[0][j] == 0 {
|
||||
for i := 1; i < len(matrix); i++ {
|
||||
matrix[i][j] = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
if isFirstRowExistZero {
|
||||
for j := 0; j < len(matrix[0]); j++ {
|
||||
matrix[0][j] = 0
|
||||
}
|
||||
}
|
||||
if isFirstColExistZero {
|
||||
for i := 0; i < len(matrix); i++ {
|
||||
matrix[i][0] = 0
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type question73 struct {
|
||||
para73
|
||||
ans73
|
||||
}
|
||||
|
||||
// para 是参数
|
||||
// one 代表第一个参数
|
||||
type para73 struct {
|
||||
matrix [][]int
|
||||
}
|
||||
|
||||
// ans 是答案
|
||||
// one 代表第一个答案
|
||||
type ans73 struct {
|
||||
}
|
||||
|
||||
func Test_Problem73(t *testing.T) {
|
||||
|
||||
qs := []question73{
|
||||
|
||||
{
|
||||
para73{[][]int{
|
||||
{0, 1, 2, 0},
|
||||
{3, 4, 5, 2},
|
||||
{1, 3, 1, 5},
|
||||
}},
|
||||
ans73{},
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Printf("------------------------Leetcode Problem 73------------------------\n")
|
||||
|
||||
for _, q := range qs {
|
||||
_, p := q.ans73, q.para73
|
||||
fmt.Printf("【input】:%v ", p)
|
||||
setZeroes(p.matrix)
|
||||
fmt.Printf("【output】:%v\n", p)
|
||||
}
|
||||
fmt.Printf("\n\n\n")
|
||||
}
|
104
leetcode/0073.Set-Matrix-Zeroes/README.md
Normal file
104
leetcode/0073.Set-Matrix-Zeroes/README.md
Normal file
@ -0,0 +1,104 @@
|
||||
# [73. Set Matrix Zeroes](https://leetcode.com/problems/set-matrix-zeroes/)
|
||||
|
||||
|
||||
## 题目
|
||||
|
||||
Given an *`m* x *n*` matrix. If an element is **0**, set its entire row and column to **0**. Do it **[in-place](https://en.wikipedia.org/wiki/In-place_algorithm)**.
|
||||
|
||||
**Follow up:**
|
||||
|
||||
- A straight forward solution using O(*mn*) space is probably a bad idea.
|
||||
- A simple improvement uses O(*m* + *n*) space, but still not the best solution.
|
||||
- Could you devise a constant space solution?
|
||||
|
||||
**Example 1:**
|
||||
|
||||

|
||||
|
||||
```
|
||||
Input: matrix = [[1,1,1],[1,0,1],[1,1,1]]
|
||||
Output: [[1,0,1],[0,0,0],[1,0,1]]
|
||||
```
|
||||
|
||||
**Example 2:**
|
||||
|
||||

|
||||
|
||||
```
|
||||
Input: matrix = [[0,1,2,0],[3,4,5,2],[1,3,1,5]]
|
||||
Output: [[0,0,0,0],[0,4,5,0],[0,3,1,0]]
|
||||
```
|
||||
|
||||
**Constraints:**
|
||||
|
||||
- `m == matrix.length`
|
||||
- `n == matrix[0].length`
|
||||
- `1 <= m, n <= 200`
|
||||
- `2^31 <= matrix[i][j] <= 2^31 - 1`
|
||||
|
||||
## 题目大意
|
||||
|
||||
给定一个 `m x n` 的矩阵,如果一个元素为 0,则将其所在行和列的所有元素都设为 0。请使用原地算法。
|
||||
|
||||
## 解题思路
|
||||
|
||||
- 此题考查对程序的控制能力,无算法思想。题目要求采用原地的算法,所有修改即在原二维数组上进行。在二维数组中有 2 个特殊位置,一个是第一行,一个是第一列。它们的特殊性在于,它们之间只要有一个 0,它们都会变为全 0 。先用 2 个变量记录这一行和这一列中是否有 0,防止之后的修改覆盖了这 2 个地方。然后除去这一行和这一列以外的部分判断是否有 0,如果有 0,将它们所在的行第一个元素标记为 0,所在列的第一个元素标记为 0 。最后通过标记,将对应的行列置 0 即可。
|
||||
|
||||
## 代码
|
||||
|
||||
```go
|
||||
package leetcode
|
||||
|
||||
func setZeroes(matrix [][]int) {
|
||||
if len(matrix) == 0 || len(matrix[0]) == 0 {
|
||||
return
|
||||
}
|
||||
isFirstRowExistZero, isFirstColExistZero := false, false
|
||||
for i := 0; i < len(matrix); i++ {
|
||||
if matrix[i][0] == 0 {
|
||||
isFirstColExistZero = true
|
||||
break
|
||||
}
|
||||
}
|
||||
for j := 0; j < len(matrix[0]); j++ {
|
||||
if matrix[0][j] == 0 {
|
||||
isFirstRowExistZero = true
|
||||
break
|
||||
}
|
||||
}
|
||||
for i := 1; i < len(matrix); i++ {
|
||||
for j := 1; j < len(matrix[0]); j++ {
|
||||
if matrix[i][j] == 0 {
|
||||
matrix[i][0] = 0
|
||||
matrix[0][j] = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
// 处理[1:]行全部置 0
|
||||
for i := 1; i < len(matrix); i++ {
|
||||
if matrix[i][0] == 0 {
|
||||
for j := 1; j < len(matrix[0]); j++ {
|
||||
matrix[i][j] = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
// 处理[1:]列全部置 0
|
||||
for j := 1; j < len(matrix[0]); j++ {
|
||||
if matrix[0][j] == 0 {
|
||||
for i := 1; i < len(matrix); i++ {
|
||||
matrix[i][j] = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
if isFirstRowExistZero {
|
||||
for j := 0; j < len(matrix[0]); j++ {
|
||||
matrix[0][j] = 0
|
||||
}
|
||||
}
|
||||
if isFirstColExistZero {
|
||||
for i := 0; i < len(matrix); i++ {
|
||||
matrix[i][0] = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
@ -1,28 +1,16 @@
|
||||
package leetcode
|
||||
|
||||
func sortColors(nums []int) {
|
||||
if len(nums) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
r := 0
|
||||
w := 0
|
||||
b := 0 // label the end of different colors;
|
||||
for _, num := range nums {
|
||||
if num == 0 {
|
||||
nums[b] = 2
|
||||
b++
|
||||
nums[w] = 1
|
||||
w++
|
||||
nums[r] = 0
|
||||
r++
|
||||
} else if num == 1 {
|
||||
nums[b] = 2
|
||||
b++
|
||||
nums[w] = 1
|
||||
w++
|
||||
} else if num == 2 {
|
||||
b++
|
||||
zero, one := 0, 0
|
||||
for i, n := range nums {
|
||||
nums[i] = 2
|
||||
if n <= 1 {
|
||||
nums[one] = 1
|
||||
one++
|
||||
}
|
||||
if n == 0 {
|
||||
nums[zero] = 0
|
||||
zero++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,9 +32,7 @@ func minWindow(s string, t string) string {
|
||||
}
|
||||
}
|
||||
if finalLeft != -1 {
|
||||
for i := finalLeft; i < finalRight+1; i++ {
|
||||
result += string(s[i])
|
||||
}
|
||||
result = string(s[finalLeft : finalRight+1])
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
@ -1,35 +1,12 @@
|
||||
package leetcode
|
||||
|
||||
func removeDuplicates80(nums []int) int {
|
||||
if len(nums) == 0 {
|
||||
return 0
|
||||
}
|
||||
last, finder := 0, 0
|
||||
for last < len(nums)-1 {
|
||||
startFinder := -1
|
||||
for nums[finder] == nums[last] {
|
||||
if startFinder == -1 || startFinder > finder {
|
||||
startFinder = finder
|
||||
}
|
||||
if finder == len(nums)-1 {
|
||||
break
|
||||
}
|
||||
finder++
|
||||
}
|
||||
if finder-startFinder >= 2 && nums[finder-1] == nums[last] && nums[finder] != nums[last] {
|
||||
nums[last+1] = nums[finder-1]
|
||||
nums[last+2] = nums[finder]
|
||||
last += 2
|
||||
} else {
|
||||
nums[last+1] = nums[finder]
|
||||
last++
|
||||
}
|
||||
if finder == len(nums)-1 {
|
||||
if nums[finder] != nums[last-1] {
|
||||
nums[last] = nums[finder]
|
||||
}
|
||||
return last + 1
|
||||
func removeDuplicates(nums []int) int {
|
||||
slow := 0
|
||||
for fast, v := range nums {
|
||||
if fast < 2 || nums[slow-2] != v {
|
||||
nums[slow] = v
|
||||
slow++
|
||||
}
|
||||
}
|
||||
return last + 1
|
||||
return slow
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ func Test_Problem80(t *testing.T) {
|
||||
|
||||
for _, q := range qs {
|
||||
_, p := q.ans80, q.para80
|
||||
fmt.Printf("【input】:%v 【output】:%v\n", p.one, removeDuplicates80(p.one))
|
||||
fmt.Printf("【input】:%v 【output】:%v\n", p.one, removeDuplicates(p.one))
|
||||
}
|
||||
fmt.Printf("\n\n\n")
|
||||
}
|
||||
|
@ -51,6 +51,6 @@ for (int i = 0; i < len; i++) {
|
||||
|
||||
## 解题思路
|
||||
|
||||
这道题和第 26 题很像。是第 26 题的加强版。这道题和第 283 题,第 27 题基本一致,283 题是删除 0,27 题是删除指定元素,这一题是删除重复元素,实质是一样的。
|
||||
|
||||
这里数组的删除并不是真的删除,只是将删除的元素移动到数组后面的空间内,然后返回数组实际剩余的元素个数,OJ 最终判断题目的时候会读取数组剩余个数的元素进行输出。
|
||||
- 问题提示有序数组,一般最容易想到使用双指针的解法,双指针的关键点:移动两个指针的条件。
|
||||
- 在该题中移动的条件:快指针从头遍历数组,慢指针指向修改后的数组的末端,当慢指针指向倒数第二个数与快指针指向的数不相等时,才移动慢指针,同时赋值慢指针。
|
||||
- 处理边界条件:当数组小于两个元素时,不做处理。
|
||||
|
@ -1,32 +1,25 @@
|
||||
package leetcode
|
||||
|
||||
import "fmt"
|
||||
|
||||
func largestRectangleArea(heights []int) int {
|
||||
maxArea, stack, height := 0, []int{}, 0
|
||||
for i := 0; i <= len(heights); i++ {
|
||||
if i == len(heights) {
|
||||
height = 0
|
||||
} else {
|
||||
height = heights[i]
|
||||
maxArea := 0
|
||||
n := len(heights) + 2
|
||||
// Add a sentry at the beginning and the end
|
||||
getHeight := func(i int) int {
|
||||
if i == 0 || n-1 == i {
|
||||
return 0
|
||||
}
|
||||
if len(stack) == 0 || height >= heights[stack[len(stack)-1]] {
|
||||
stack = append(stack, i)
|
||||
} else {
|
||||
tmp := stack[len(stack)-1]
|
||||
fmt.Printf("1. tmp = %v stack = %v\n", tmp, stack)
|
||||
stack = stack[:len(stack)-1]
|
||||
length := 0
|
||||
if len(stack) == 0 {
|
||||
length = i
|
||||
} else {
|
||||
length = i - 1 - stack[len(stack)-1]
|
||||
fmt.Printf("2. length = %v stack = %v i = %v\n", length, stack, i)
|
||||
}
|
||||
maxArea = max(maxArea, heights[tmp]*length)
|
||||
fmt.Printf("3. maxArea = %v heights[tmp]*length = %v\n", maxArea, heights[tmp]*length)
|
||||
i--
|
||||
return heights[i-1]
|
||||
}
|
||||
st := make([]int, 0, n/2)
|
||||
for i := 0; i < n; i++ {
|
||||
for len(st) > 0 && getHeight(st[len(st)-1]) > getHeight(i) {
|
||||
// pop stack
|
||||
idx := st[len(st)-1]
|
||||
st = st[:len(st)-1]
|
||||
maxArea = max(maxArea, getHeight(idx)*(i-st[len(st)-1]-1))
|
||||
}
|
||||
// push stack
|
||||
st = append(st, i)
|
||||
}
|
||||
return maxArea
|
||||
}
|
||||
|
@ -40,6 +40,10 @@ func Test_Problem84(t *testing.T) {
|
||||
para84{[]int{1, 1}},
|
||||
ans84{2},
|
||||
},
|
||||
{
|
||||
para84{[]int{2, 1, 2}},
|
||||
ans84{3},
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Printf("------------------------Leetcode Problem 84------------------------\n")
|
||||
|
@ -1,29 +1,16 @@
|
||||
package leetcode
|
||||
|
||||
func merge(nums1 []int, m int, nums2 []int, n int) {
|
||||
if m == 0 {
|
||||
copy(nums1, nums2)
|
||||
return
|
||||
}
|
||||
// 这里不需要,因为测试数据考虑到了第一个数组的空间问题
|
||||
// for index := 0; index < n; index++ {
|
||||
// nums1 = append(nums1, nums2[index])
|
||||
// }
|
||||
i := m - 1
|
||||
j := n - 1
|
||||
k := m + n - 1
|
||||
// 从后面往前放,只需要循环一次即可
|
||||
for ; i >= 0 && j >= 0; k-- {
|
||||
if nums1[i] > nums2[j] {
|
||||
nums1[k] = nums1[i]
|
||||
i--
|
||||
for p := m + n; m > 0 && n > 0; p-- {
|
||||
if nums1[m-1] <= nums2[n-1] {
|
||||
nums1[p-1] = nums2[n-1]
|
||||
n--
|
||||
} else {
|
||||
nums1[k] = nums2[j]
|
||||
j--
|
||||
nums1[p-1] = nums1[m-1]
|
||||
m--
|
||||
}
|
||||
}
|
||||
for ; j >= 0; k-- {
|
||||
nums1[k] = nums2[j]
|
||||
j--
|
||||
for ; n > 0; n-- {
|
||||
nums1[n-1] = nums2[n-1]
|
||||
}
|
||||
}
|
||||
|
@ -29,20 +29,10 @@ func Test_Problem88(t *testing.T) {
|
||||
|
||||
qs := []question88{
|
||||
|
||||
// question{
|
||||
// para{[]int{0}, 0, []int{1}, 1},
|
||||
// ans{[]int{1}},
|
||||
// },
|
||||
//
|
||||
// question{
|
||||
// para{[]int{1, 3, 5, 7}, 4, []int{2, 4}, 2},
|
||||
// ans{[]int{1, 2, 3, 4}},
|
||||
// },
|
||||
//
|
||||
// question{
|
||||
// para{[]int{1, 3, 5, 7}, 4, []int{2, 2}, 2},
|
||||
// ans{[]int{1, 2, 2, 3}},
|
||||
// },
|
||||
{
|
||||
para88{[]int{0}, 0, []int{1}, 1},
|
||||
ans88{[]int{1}},
|
||||
},
|
||||
|
||||
{
|
||||
para88{[]int{1, 2, 3, 0, 0, 0}, 3, []int{2, 5, 6}, 3},
|
||||
|
@ -1,29 +1,16 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func numDecodings(s string) int {
|
||||
if len(s) == 0 {
|
||||
return 0
|
||||
}
|
||||
dp := make([]int, len(s)+1)
|
||||
n := len(s)
|
||||
dp := make([]int, n+1)
|
||||
dp[0] = 1
|
||||
if s[:1] == "0" {
|
||||
dp[1] = 0
|
||||
} else {
|
||||
dp[1] = 1
|
||||
}
|
||||
for i := 2; i <= len(s); i++ {
|
||||
lastNum, _ := strconv.Atoi(s[i-1 : i])
|
||||
if lastNum >= 1 && lastNum <= 9 {
|
||||
for i := 1; i <= n; i++ {
|
||||
if s[i-1] != '0' {
|
||||
dp[i] += dp[i-1]
|
||||
}
|
||||
lastNum, _ = strconv.Atoi(s[i-2 : i])
|
||||
if lastNum >= 10 && lastNum <= 26 {
|
||||
if i > 1 && s[i-2] != '0' && (s[i-2]-'0')*10+(s[i-1]-'0') <= 26 {
|
||||
dp[i] += dp[i-2]
|
||||
}
|
||||
}
|
||||
return dp[len(s)]
|
||||
return dp[n]
|
||||
}
|
||||
|
35
leetcode/0097.Interleaving-String/97. Interleaving String.go
Normal file
35
leetcode/0097.Interleaving-String/97. Interleaving String.go
Normal file
@ -0,0 +1,35 @@
|
||||
package leetcode
|
||||
|
||||
func isInterleave(s1 string, s2 string, s3 string) bool {
|
||||
if len(s1)+len(s2) != len(s3) {
|
||||
return false
|
||||
}
|
||||
visited := make(map[int]bool)
|
||||
return dfs(s1, s2, s3, 0, 0, visited)
|
||||
}
|
||||
|
||||
func dfs(s1, s2, s3 string, p1, p2 int, visited map[int]bool) bool {
|
||||
if p1+p2 == len(s3) {
|
||||
return true
|
||||
}
|
||||
if _, ok := visited[(p1*len(s3))+p2]; ok {
|
||||
return false
|
||||
}
|
||||
visited[(p1*len(s3))+p2] = true
|
||||
var match1, match2 bool
|
||||
if p1 < len(s1) && s3[p1+p2] == s1[p1] {
|
||||
match1 = true
|
||||
}
|
||||
if p2 < len(s2) && s3[p1+p2] == s2[p2] {
|
||||
match2 = true
|
||||
}
|
||||
if match1 && match2 {
|
||||
return dfs(s1, s2, s3, p1+1, p2, visited) || dfs(s1, s2, s3, p1, p2+1, visited)
|
||||
} else if match1 {
|
||||
return dfs(s1, s2, s3, p1+1, p2, visited)
|
||||
} else if match2 {
|
||||
return dfs(s1, s2, s3, p1, p2+1, visited)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type question97 struct {
|
||||
para97
|
||||
ans97
|
||||
}
|
||||
|
||||
// para 是参数
|
||||
// one 代表第一个参数
|
||||
type para97 struct {
|
||||
s1 string
|
||||
s2 string
|
||||
s3 string
|
||||
}
|
||||
|
||||
// ans 是答案
|
||||
// one 代表第一个答案
|
||||
type ans97 struct {
|
||||
one bool
|
||||
}
|
||||
|
||||
func Test_Problem97(t *testing.T) {
|
||||
|
||||
qs := []question97{
|
||||
|
||||
{
|
||||
para97{"aabcc", "dbbca", "aadbbcbcac"},
|
||||
ans97{true},
|
||||
},
|
||||
|
||||
{
|
||||
para97{"aabcc", "dbbca", "aadbbbaccc"},
|
||||
ans97{false},
|
||||
},
|
||||
|
||||
{
|
||||
para97{"", "", ""},
|
||||
ans97{true},
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Printf("------------------------Leetcode Problem 97------------------------\n")
|
||||
|
||||
for _, q := range qs {
|
||||
_, p := q.ans97, q.para97
|
||||
fmt.Printf("【input】:%v 【output】:%v\n", p, isInterleave(p.s1, p.s2, p.s3))
|
||||
}
|
||||
fmt.Printf("\n\n\n")
|
||||
}
|
104
leetcode/0097.Interleaving-String/README.md
Normal file
104
leetcode/0097.Interleaving-String/README.md
Normal file
@ -0,0 +1,104 @@
|
||||
# [97. Interleaving String](https://leetcode.com/problems/interleaving-string/)
|
||||
|
||||
|
||||
## 题目
|
||||
|
||||
Given strings `s1`, `s2`, and `s3`, find whether `s3` is formed by an **interleaving** of `s1` and `s2`.
|
||||
|
||||
An **interleaving** of two strings `s` and `t` is a configuration where they are divided into **non-empty** substrings such that:
|
||||
|
||||
- `s = s1 + s2 + ... + sn`
|
||||
- `t = t1 + t2 + ... + tm`
|
||||
- `|n - m| <= 1`
|
||||
- The **interleaving** is `s1 + t1 + s2 + t2 + s3 + t3 + ...` or `t1 + s1 + t2 + s2 + t3 + s3 + ...`
|
||||
|
||||
**Note:** `a + b` is the concatenation of strings `a` and `b`.
|
||||
|
||||
**Example 1:**
|
||||
|
||||

|
||||
|
||||
```
|
||||
Input: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac"
|
||||
Output: true
|
||||
|
||||
```
|
||||
|
||||
**Example 2:**
|
||||
|
||||
```
|
||||
Input: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbbaccc"
|
||||
Output: false
|
||||
|
||||
```
|
||||
|
||||
**Example 3:**
|
||||
|
||||
```
|
||||
Input: s1 = "", s2 = "", s3 = ""
|
||||
Output: true
|
||||
|
||||
```
|
||||
|
||||
**Constraints:**
|
||||
|
||||
- `0 <= s1.length, s2.length <= 100`
|
||||
- `0 <= s3.length <= 200`
|
||||
- `s1`, `s2`, and `s3` consist of lowercase English letters.
|
||||
|
||||
**Follow up:** Could you solve it using only `O(s2.length)` additional memory space?
|
||||
|
||||
## 题目大意
|
||||
|
||||
给定三个字符串 s1、s2、s3,请你帮忙验证 s3 是否是由 s1 和 s2 交错 组成的。两个字符串 s 和 t 交错 的定义与过程如下,其中每个字符串都会被分割成若干 非空 子字符串:
|
||||
|
||||
- s = s1 + s2 + ... + sn
|
||||
- t = t1 + t2 + ... + tm
|
||||
- |n - m| <= 1
|
||||
- 交错 是 s1 + t1 + s2 + t2 + s3 + t3 + ... 或者 t1 + s1 + t2 + s2 + t3 + s3 + ...
|
||||
|
||||
提示:a + b 意味着字符串 a 和 b 连接。
|
||||
|
||||
## 解题思路
|
||||
|
||||
- 深搜或者广搜暴力解题。笔者用深搜实现的。记录 s1 和 s2 串当前比较的位置 p1 和 p2。如果 s3[p1+p2] 的位置上等于 s1[p1] 或者 s2[p2] 代表能匹配上,那么继续往后移动 p1 和 p2 相应的位置。因为是交错字符串,所以判断匹配的位置是 s3[p1+p2] 的位置。如果仅仅这么写,会超时,s1 和 s2 两个字符串重复交叉判断的位置太多了。需要加上记忆化搜索。可以用 visited[i][j] 这样的二维数组来记录是否搜索过了。笔者为了压缩空间,将 i 和 j 编码压缩到一维数组了。i * len(s3) + j 是唯一下标,所以可以用这种方式存储是否搜索过。具体代码见下面的实现。
|
||||
|
||||
## 代码
|
||||
|
||||
```go
|
||||
package leetcode
|
||||
|
||||
func isInterleave(s1 string, s2 string, s3 string) bool {
|
||||
if len(s1)+len(s2) != len(s3) {
|
||||
return false
|
||||
}
|
||||
visited := make(map[int]bool)
|
||||
return dfs(s1, s2, s3, 0, 0, visited)
|
||||
}
|
||||
|
||||
func dfs(s1, s2, s3 string, p1, p2 int, visited map[int]bool) bool {
|
||||
if p1+p2 == len(s3) {
|
||||
return true
|
||||
}
|
||||
if _, ok := visited[(p1*len(s3))+p2]; ok {
|
||||
return false
|
||||
}
|
||||
visited[(p1*len(s3))+p2] = true
|
||||
var match1, match2 bool
|
||||
if p1 < len(s1) && s3[p1+p2] == s1[p1] {
|
||||
match1 = true
|
||||
}
|
||||
if p2 < len(s2) && s3[p1+p2] == s2[p2] {
|
||||
match2 = true
|
||||
}
|
||||
if match1 && match2 {
|
||||
return dfs(s1, s2, s3, p1+1, p2, visited) || dfs(s1, s2, s3, p1, p2+1, visited)
|
||||
} else if match1 {
|
||||
return dfs(s1, s2, s3, p1+1, p2, visited)
|
||||
} else if match2 {
|
||||
return dfs(s1, s2, s3, p1, p2+1, visited)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
```
|
@ -16,7 +16,26 @@ type TreeNode = structures.TreeNode
|
||||
* }
|
||||
*/
|
||||
|
||||
// 解法一 dfs
|
||||
func isSymmetric(root *TreeNode) bool {
|
||||
if root == nil {
|
||||
return true
|
||||
}
|
||||
return isMirror(root.Left, root.Right)
|
||||
}
|
||||
|
||||
func isMirror(left *TreeNode, right *TreeNode) bool {
|
||||
if left == nil && right == nil {
|
||||
return true
|
||||
}
|
||||
if left == nil || right == nil {
|
||||
return false
|
||||
}
|
||||
return (left.Val == right.Val) && isMirror(left.Left, right.Right) && isMirror(left.Right, right.Left)
|
||||
}
|
||||
|
||||
// 解法二
|
||||
func isSymmetric1(root *TreeNode) bool {
|
||||
if root == nil {
|
||||
return true
|
||||
}
|
||||
|
@ -21,50 +21,42 @@ func levelOrder(root *TreeNode) [][]int {
|
||||
if root == nil {
|
||||
return [][]int{}
|
||||
}
|
||||
queue := []*TreeNode{}
|
||||
queue = append(queue, root)
|
||||
curNum, nextLevelNum, res, tmp := 1, 0, [][]int{}, []int{}
|
||||
for len(queue) != 0 {
|
||||
if curNum > 0 {
|
||||
node := queue[0]
|
||||
if node.Left != nil {
|
||||
queue = append(queue, node.Left)
|
||||
nextLevelNum++
|
||||
queue := []*TreeNode{root}
|
||||
res := make([][]int, 0)
|
||||
for len(queue) > 0 {
|
||||
l := len(queue)
|
||||
tmp := make([]int, 0, l)
|
||||
for i := 0; i < l; i++ {
|
||||
if queue[i].Left != nil {
|
||||
queue = append(queue, queue[i].Left)
|
||||
}
|
||||
if node.Right != nil {
|
||||
queue = append(queue, node.Right)
|
||||
nextLevelNum++
|
||||
if queue[i].Right != nil {
|
||||
queue = append(queue, queue[i].Right)
|
||||
}
|
||||
curNum--
|
||||
tmp = append(tmp, node.Val)
|
||||
queue = queue[1:]
|
||||
}
|
||||
if curNum == 0 {
|
||||
res = append(res, tmp)
|
||||
curNum = nextLevelNum
|
||||
nextLevelNum = 0
|
||||
tmp = []int{}
|
||||
tmp = append(tmp, queue[i].Val)
|
||||
}
|
||||
queue = queue[l:]
|
||||
res = append(res, tmp)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// 解法二 DFS
|
||||
func levelOrder1(root *TreeNode) [][]int {
|
||||
levels := [][]int{}
|
||||
dfsLevel(root, -1, &levels)
|
||||
return levels
|
||||
}
|
||||
|
||||
func dfsLevel(node *TreeNode, level int, res *[][]int) {
|
||||
if node == nil {
|
||||
return
|
||||
var res [][]int
|
||||
var dfsLevel func(node *TreeNode, level int)
|
||||
dfsLevel = func(node *TreeNode, level int) {
|
||||
if node == nil {
|
||||
return
|
||||
}
|
||||
if len(res) == level {
|
||||
res = append(res, []int{node.Val})
|
||||
} else {
|
||||
res[level] = append(res[level], node.Val)
|
||||
}
|
||||
dfsLevel(node.Left, level+1)
|
||||
dfsLevel(node.Right, level+1)
|
||||
}
|
||||
currLevel := level + 1
|
||||
for len(*res) <= currLevel {
|
||||
*res = append(*res, []int{})
|
||||
}
|
||||
(*res)[currLevel] = append((*res)[currLevel], node.Val)
|
||||
dfsLevel(node.Left, currLevel, res)
|
||||
dfsLevel(node.Right, currLevel, res)
|
||||
dfsLevel(root, 0)
|
||||
return res
|
||||
}
|
||||
|
@ -81,3 +81,40 @@ func search(root *TreeNode, depth int, res *[][]int) {
|
||||
search(root.Left, depth+1, res)
|
||||
search(root.Right, depth+1, res)
|
||||
}
|
||||
|
||||
// 解法三 BFS
|
||||
func zigzagLevelOrder1(root *TreeNode) [][]int {
|
||||
res := [][]int{}
|
||||
if root == nil {
|
||||
return res
|
||||
}
|
||||
q := []*TreeNode{root}
|
||||
size, i, j, lay, tmp, flag := 0, 0, 0, []int{}, []*TreeNode{}, false
|
||||
for len(q) > 0 {
|
||||
size = len(q)
|
||||
tmp = []*TreeNode{}
|
||||
lay = make([]int, size)
|
||||
j = size - 1
|
||||
for i = 0; i < size; i++ {
|
||||
root = q[0]
|
||||
q = q[1:]
|
||||
if !flag {
|
||||
lay[i] = root.Val
|
||||
} else {
|
||||
lay[j] = root.Val
|
||||
j--
|
||||
}
|
||||
if root.Left != nil {
|
||||
tmp = append(tmp, root.Left)
|
||||
}
|
||||
if root.Right != nil {
|
||||
tmp = append(tmp, root.Right)
|
||||
}
|
||||
|
||||
}
|
||||
res = append(res, lay)
|
||||
flag = !flag
|
||||
q = tmp
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
@ -16,7 +16,23 @@ type TreeNode = structures.TreeNode
|
||||
* }
|
||||
*/
|
||||
|
||||
// 解法一, 直接传入需要的 slice 范围作为输入, 可以避免申请对应 inorder 索引的内存, 内存使用(leetcode test case) 4.7MB -> 4.3MB.
|
||||
func buildTree(preorder []int, inorder []int) *TreeNode {
|
||||
if len(preorder) == 0 {
|
||||
return nil
|
||||
}
|
||||
root := &TreeNode{Val: preorder[0]}
|
||||
for pos, node := range inorder {
|
||||
if node == root.Val {
|
||||
root.Left = buildTree(preorder[1:pos+1], inorder[:pos])
|
||||
root.Right = buildTree(preorder[pos+1:], inorder[pos+1:])
|
||||
}
|
||||
}
|
||||
return root
|
||||
}
|
||||
|
||||
// 解法二
|
||||
func buildTree1(preorder []int, inorder []int) *TreeNode {
|
||||
inPos := make(map[int]int)
|
||||
for i := 0; i < len(inorder); i++ {
|
||||
inPos[inorder[i]] = i
|
||||
|
@ -16,7 +16,25 @@ type TreeNode = structures.TreeNode
|
||||
* }
|
||||
*/
|
||||
|
||||
// 解法一, 直接传入需要的 slice 范围作为输入, 可以避免申请对应 inorder 索引的内存, 内存使用(leetcode test case) 4.7MB -> 4.3MB.
|
||||
func buildTree(inorder []int, postorder []int) *TreeNode {
|
||||
postorderLen := len(postorder)
|
||||
if len(inorder) == 0 {
|
||||
return nil
|
||||
}
|
||||
root := &TreeNode{Val: postorder[postorderLen-1]}
|
||||
postorder = postorder[:postorderLen-1]
|
||||
for pos, node := range inorder {
|
||||
if node == root.Val {
|
||||
root.Left = buildTree(inorder[:pos], postorder[:len(inorder[:pos])])
|
||||
root.Right = buildTree(inorder[pos+1:], postorder[len(inorder[:pos]):])
|
||||
}
|
||||
}
|
||||
return root
|
||||
}
|
||||
|
||||
// 解法二
|
||||
func buildTree1(inorder []int, postorder []int) *TreeNode {
|
||||
inPos := make(map[int]int)
|
||||
for i := 0; i < len(inorder); i++ {
|
||||
inPos[inorder[i]] = i
|
||||
|
@ -0,0 +1,45 @@
|
||||
package leetcode
|
||||
|
||||
// 解法一 压缩版 DP
|
||||
func numDistinct(s string, t string) int {
|
||||
dp := make([]int, len(s)+1)
|
||||
for i, curT := range t {
|
||||
pre := 0
|
||||
for j, curS := range s {
|
||||
if i == 0 {
|
||||
pre = 1
|
||||
}
|
||||
newDP := dp[j+1]
|
||||
if curT == curS {
|
||||
dp[j+1] = dp[j] + pre
|
||||
} else {
|
||||
dp[j+1] = dp[j]
|
||||
}
|
||||
pre = newDP
|
||||
}
|
||||
}
|
||||
return dp[len(s)]
|
||||
}
|
||||
|
||||
// 解法二 普通 DP
|
||||
func numDistinct1(s, t string) int {
|
||||
m, n := len(s), len(t)
|
||||
if m < n {
|
||||
return 0
|
||||
}
|
||||
dp := make([][]int, m+1)
|
||||
for i := range dp {
|
||||
dp[i] = make([]int, n+1)
|
||||
dp[i][n] = 1
|
||||
}
|
||||
for i := m - 1; i >= 0; i-- {
|
||||
for j := n - 1; j >= 0; j-- {
|
||||
if s[i] == t[j] {
|
||||
dp[i][j] = dp[i+1][j+1] + dp[i+1][j]
|
||||
} else {
|
||||
dp[i][j] = dp[i+1][j]
|
||||
}
|
||||
}
|
||||
}
|
||||
return dp[0][0]
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type question115 struct {
|
||||
para115
|
||||
ans115
|
||||
}
|
||||
|
||||
// para 是参数
|
||||
// one 代表第一个参数
|
||||
type para115 struct {
|
||||
s string
|
||||
t string
|
||||
}
|
||||
|
||||
// ans 是答案
|
||||
// one 代表第一个答案
|
||||
type ans115 struct {
|
||||
one int
|
||||
}
|
||||
|
||||
func Test_Problem115(t *testing.T) {
|
||||
|
||||
qs := []question115{
|
||||
|
||||
{
|
||||
para115{"rabbbit", "rabbit"},
|
||||
ans115{3},
|
||||
},
|
||||
|
||||
{
|
||||
para115{"babgbag", "bag"},
|
||||
ans115{5},
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Printf("------------------------Leetcode Problem 115------------------------\n")
|
||||
|
||||
for _, q := range qs {
|
||||
_, p := q.ans115, q.para115
|
||||
fmt.Printf("【input】:%v 【output】:%v\n", p, numDistinct(p.s, p.t))
|
||||
}
|
||||
fmt.Printf("\n\n\n")
|
||||
}
|
99
leetcode/0115.Distinct-Subsequences/README.md
Normal file
99
leetcode/0115.Distinct-Subsequences/README.md
Normal file
@ -0,0 +1,99 @@
|
||||
# [115. Distinct Subsequences](https://leetcode.com/problems/distinct-subsequences/)
|
||||
|
||||
|
||||
## 题目
|
||||
|
||||
Given two strings `s` and `t`, return *the number of distinct subsequences of `s` which equals `t`*.
|
||||
|
||||
A string's **subsequence** is a new string formed from the original string by deleting some (can be none) of the characters without disturbing the remaining characters' relative positions. (i.e., `"ACE"` is a subsequence of `"ABCDE"` while `"AEC"` is not).
|
||||
|
||||
It is guaranteed the answer fits on a 32-bit signed integer.
|
||||
|
||||
**Example 1:**
|
||||
|
||||
```
|
||||
Input: s = "rabbbit", t = "rabbit"
|
||||
Output: 3
|
||||
Explanation:
|
||||
As shown below, there are 3 ways you can generate "rabbit" from S.
|
||||
rabbbitrabbbitrabbbit
|
||||
```
|
||||
|
||||
**Example 2:**
|
||||
|
||||
```
|
||||
Input: s = "babgbag", t = "bag"
|
||||
Output: 5
|
||||
Explanation:
|
||||
As shown below, there are 5 ways you can generate "bag" from S.
|
||||
babgbagbabgbagbabgbagbabgbagbabgbag
|
||||
```
|
||||
|
||||
**Constraints:**
|
||||
|
||||
- `0 <= s.length, t.length <= 1000`
|
||||
- `s` and `t` consist of English letters.
|
||||
|
||||
## 题目大意
|
||||
|
||||
给定一个字符串 s 和一个字符串 t ,计算在 s 的子序列中 t 出现的个数。字符串的一个 子序列 是指,通过删除一些(也可以不删除)字符且不干扰剩余字符相对位置所组成的新字符串。(例如,"ACE" 是 "ABCDE" 的一个子序列,而 "AEC" 不是)题目数据保证答案符合 32 位带符号整数范围。
|
||||
|
||||
## 解题思路
|
||||
|
||||
- 在字符串 `s` 中最多包含多少个字符串 `t`。这里面包含很多重叠子问题,所以尝试用动态规划解决这个问题。定义 `dp[i][j]` 代表 `s[i:]` 的子序列中 `t[j:]` 出现的个数。初始化先判断边界条件。当 `i = len(s)` 且 `0≤ j < len(t)` 的时候,`s[i:]` 为空字符串,`t[j:]` 不为空,所以 `dp[len(s)][j] = 0`。当 `j = len(t)` 且 `0 ≤ i < len(s)` 的时候,`t[j:]` 不为空字符串,空字符串是任何字符串的子序列。所以 `dp[i][n] = 1`。
|
||||
- 当 `i < len(s)` 且 `j < len(t)` 的时候,如果 `s[i] == t[j]`,有 2 种匹配方式,第一种将 `s[i]` 与 `t[j]` 匹配,那么 `t[j+1:]` 匹配 `s[i+1:]` 的子序列,子序列数为 `dp[i+1][j+1]`;第二种将 `s[i]` 不与 `t[j]` 匹配,`t[j:]` 作为 `s[i+1:]` 的子序列,子序列数为 `dp[i+1][j]`。综合 2 种情况,当 `s[i] == t[j]` 时,`dp[i][j] = dp[i+1][j+1] + dp[i+1][j]`。
|
||||
- 如果 `s[i] != t[j]`,此时 `t[j:]` 只能作为 `s[i+1:]` 的子序列,子序列数为 `dp[i+1][j]`。所以当 `s[i] != t[j]` 时,`dp[i][j] = dp[i+1][j]`。综上分析得:
|
||||
|
||||
$$dp[i][j] = \left\{\begin{matrix}dp[i+1][j+1]+dp[i+1][j]&,s[i]=t[j]\\ dp[i+1][j]&,s[i]!=t[j]\end{matrix}\right.$$
|
||||
|
||||
- 最后是优化版本。写出上述代码以后,可以发现填表的过程是从右下角一直填到左上角。填表顺序是 从下往上一行一行的填。行内从右往左填。于是可以将这个二维数据压缩到一维。因为填充当前行只需要用到它的下一行信息即可,更进一步,用到的是下一行中右边元素的信息。于是可以每次更新该行时,先将旧的值存起来,计算更新该行的时候从右往左更新。这样做即可减少一维空间,将原来的二维数组压缩到一维数组。
|
||||
|
||||
## 代码
|
||||
|
||||
```go
|
||||
package leetcode
|
||||
|
||||
// 解法一 压缩版 DP
|
||||
func numDistinct(s string, t string) int {
|
||||
dp := make([]int, len(s)+1)
|
||||
for i, curT := range t {
|
||||
pre := 0
|
||||
for j, curS := range s {
|
||||
if i == 0 {
|
||||
pre = 1
|
||||
}
|
||||
newDP := dp[j+1]
|
||||
if curT == curS {
|
||||
dp[j+1] = dp[j] + pre
|
||||
} else {
|
||||
dp[j+1] = dp[j]
|
||||
}
|
||||
pre = newDP
|
||||
}
|
||||
}
|
||||
return dp[len(s)]
|
||||
}
|
||||
|
||||
// 解法二 普通 DP
|
||||
func numDistinct1(s, t string) int {
|
||||
m, n := len(s), len(t)
|
||||
if m < n {
|
||||
return 0
|
||||
}
|
||||
dp := make([][]int, m+1)
|
||||
for i := range dp {
|
||||
dp[i] = make([]int, n+1)
|
||||
dp[i][n] = 1
|
||||
}
|
||||
for i := m - 1; i >= 0; i-- {
|
||||
for j := n - 1; j >= 0; j-- {
|
||||
if s[i] == t[j] {
|
||||
dp[i][j] = dp[i+1][j+1] + dp[i+1][j]
|
||||
} else {
|
||||
dp[i][j] = dp[i+1][j]
|
||||
}
|
||||
}
|
||||
}
|
||||
return dp[0][0]
|
||||
}
|
||||
```
|
@ -0,0 +1,52 @@
|
||||
package leetcode
|
||||
|
||||
type Node struct {
|
||||
Val int
|
||||
Left *Node
|
||||
Right *Node
|
||||
Next *Node
|
||||
}
|
||||
|
||||
//解法一:迭代
|
||||
func connect(root *Node) *Node {
|
||||
if root == nil {
|
||||
return root
|
||||
}
|
||||
q := []*Node{root}
|
||||
for len(q) > 0 {
|
||||
var p []*Node
|
||||
// 遍历这一层的所有节点
|
||||
for i, node := range q {
|
||||
if i+1 < len(q) {
|
||||
node.Next = q[i+1]
|
||||
}
|
||||
if node.Left != nil {
|
||||
p = append(p, node.Left)
|
||||
}
|
||||
if node.Right != nil {
|
||||
p = append(p, node.Right)
|
||||
}
|
||||
}
|
||||
q = p
|
||||
}
|
||||
return root
|
||||
}
|
||||
|
||||
// 解法二 递归
|
||||
func connect2(root *Node) *Node {
|
||||
if root == nil {
|
||||
return nil
|
||||
}
|
||||
connectTwoNode(root.Left, root.Right)
|
||||
return root
|
||||
}
|
||||
|
||||
func connectTwoNode(node1, node2 *Node) {
|
||||
if node1 == nil || node2 == nil {
|
||||
return
|
||||
}
|
||||
node1.Next = node2
|
||||
connectTwoNode(node1.Left, node1.Right)
|
||||
connectTwoNode(node2.Left, node2.Right)
|
||||
connectTwoNode(node1.Right, node2.Left)
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type question116 struct {
|
||||
para116
|
||||
ans116
|
||||
}
|
||||
|
||||
// para 是参数
|
||||
// one 代表第一个参数
|
||||
type para116 struct {
|
||||
one *Node
|
||||
}
|
||||
|
||||
// ans 是答案
|
||||
// one 代表第一个答案
|
||||
type ans116 struct {
|
||||
one *Node
|
||||
}
|
||||
|
||||
func newQuestionNode()*Node{
|
||||
node7 := &Node{}
|
||||
node7.Val = 7
|
||||
|
||||
node6 := &Node{}
|
||||
node6.Val = 6
|
||||
|
||||
node5 := &Node{}
|
||||
node5.Val = 5
|
||||
|
||||
node4 := &Node{}
|
||||
node4.Val = 4
|
||||
|
||||
node3 := &Node{}
|
||||
node3.Val = 3
|
||||
|
||||
node2 := &Node{}
|
||||
node2.Val = 2
|
||||
|
||||
node1 := &Node{}
|
||||
node1.Val = 1
|
||||
|
||||
node1.Left = node2
|
||||
node1.Right = node3
|
||||
|
||||
node2.Left = node4
|
||||
node2.Right = node5
|
||||
|
||||
node3.Left = node6
|
||||
node3.Right = node7
|
||||
return node1
|
||||
}
|
||||
|
||||
func newResultNode()*Node{
|
||||
node7 := &Node{}
|
||||
node7.Val = 7
|
||||
|
||||
node6 := &Node{}
|
||||
node6.Val = 6
|
||||
|
||||
node5 := &Node{}
|
||||
node5.Val = 5
|
||||
|
||||
node4 := &Node{}
|
||||
node4.Val = 4
|
||||
|
||||
node3 := &Node{}
|
||||
node3.Val = 3
|
||||
|
||||
node2 := &Node{}
|
||||
node2.Val = 2
|
||||
|
||||
node1 := &Node{}
|
||||
node1.Val = 1
|
||||
|
||||
node1.Left = node2
|
||||
node1.Right = node3
|
||||
|
||||
node2.Left = node4
|
||||
node2.Right = node5
|
||||
|
||||
node3.Left = node6
|
||||
node3.Right = node7
|
||||
|
||||
node1.Next = nil
|
||||
node2.Next = node3
|
||||
node3.Next = nil
|
||||
node4.Next = node5
|
||||
node5.Next = node6
|
||||
node6.Next = node7
|
||||
node7.Next = nil
|
||||
|
||||
return node1
|
||||
}
|
||||
|
||||
func Test_Problem116(t *testing.T) {
|
||||
|
||||
qs := []question116{
|
||||
{
|
||||
para116{newQuestionNode()},
|
||||
ans116{newResultNode()},
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Printf("------------------------Leetcode Problem 116------------------------\n")
|
||||
|
||||
for _, q := range qs {
|
||||
_, p := q.ans116, q.para116
|
||||
fmt.Printf("【input】:%v ", p.one)
|
||||
fmt.Printf("【output】:%v \n", connect(p.one))
|
||||
}
|
||||
fmt.Printf("\n\n\n")
|
||||
}
|
@ -0,0 +1,118 @@
|
||||
# [116. Populating Next Right Pointers in Each Node](https://leetcode.com/problems/populating-next-right-pointers-in-each-node/)
|
||||
|
||||
|
||||
## 题目
|
||||
|
||||
You are given a **perfect binary tree** where all leaves are on the same level, and every parent has two children. The binary tree has the following definition:
|
||||
|
||||
```
|
||||
struct Node {
|
||||
int val;
|
||||
Node *left;
|
||||
Node *right;
|
||||
Node *next;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Populate each next pointer to point to its next right node. If there is no next right node, the next pointer should be set to `NULL`.
|
||||
|
||||
Initially, all next pointers are set to `NULL`.
|
||||
|
||||
**Follow up:**
|
||||
|
||||
- You may only use constant extra space.
|
||||
- Recursive approach is fine, you may assume implicit stack space does not count as extra space for this problem.
|
||||
|
||||
**Example 1:**
|
||||
|
||||

|
||||
|
||||
```
|
||||
Input: root = [1,2,3,4,5,6,7]
|
||||
Output: [1,#,2,3,#,4,5,6,7,#]
|
||||
Explanation:Given the above perfect binary tree (Figure A), your function should populate each next pointer to point to its next right node, just like in Figure B. The serialized output is in level order as connected by the next pointers, with '#' signifying the end of each level.
|
||||
|
||||
```
|
||||
|
||||
**Constraints:**
|
||||
|
||||
- The number of nodes in the given tree is less than `4096`.
|
||||
- `1000 <= node.val <= 1000`
|
||||
|
||||
## 题目大意
|
||||
|
||||
给定一个 完美二叉树 ,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:
|
||||
|
||||
```jsx
|
||||
struct Node {
|
||||
int val;
|
||||
Node *left;
|
||||
Node *right;
|
||||
Node *next;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。初始状态下,所有 next 指针都被设置为 NULL。
|
||||
|
||||
## 解题思路
|
||||
|
||||
- 本质上是二叉树的层序遍历,基于广度优先搜索,将每层的节点放入队列,并遍历队列进行连接。
|
||||
|
||||
## 代码
|
||||
|
||||
```go
|
||||
package leetcode
|
||||
|
||||
type Node struct {
|
||||
Val int
|
||||
Left *Node
|
||||
Right *Node
|
||||
Next *Node
|
||||
}
|
||||
|
||||
//解法一:迭代
|
||||
func connect(root *Node) *Node {
|
||||
if root == nil {
|
||||
return root
|
||||
}
|
||||
q := []*Node{root}
|
||||
for len(q) > 0 {
|
||||
var p []*Node
|
||||
// 遍历这一层的所有节点
|
||||
for i, node := range q {
|
||||
if i+1 < len(q) {
|
||||
node.Next = q[i+1]
|
||||
}
|
||||
if node.Left != nil {
|
||||
p = append(p, node.Left)
|
||||
}
|
||||
if node.Right != nil {
|
||||
p = append(p, node.Right)
|
||||
}
|
||||
}
|
||||
q = p
|
||||
}
|
||||
return root
|
||||
}
|
||||
|
||||
// 解法二 递归
|
||||
func connect2(root *Node) *Node {
|
||||
if root == nil {
|
||||
return nil
|
||||
}
|
||||
connectTwoNode(root.Left, root.Right)
|
||||
return root
|
||||
}
|
||||
|
||||
func connectTwoNode(node1, node2 *Node) {
|
||||
if node1 == nil || node2 == nil {
|
||||
return
|
||||
}
|
||||
node1.Next = node2
|
||||
connectTwoNode(node1.Left, node1.Right)
|
||||
connectTwoNode(node2.Left, node2.Right)
|
||||
connectTwoNode(node1.Right, node2.Left)
|
||||
}
|
||||
```
|
@ -1,9 +1,5 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
import (
|
||||
"github.com/halfrost/LeetCode-Go/structures"
|
||||
)
|
||||
@ -21,29 +17,20 @@ type TreeNode = structures.TreeNode
|
||||
*/
|
||||
|
||||
func sumNumbers(root *TreeNode) int {
|
||||
res, nums := 0, binaryTreeNums(root)
|
||||
for _, n := range nums {
|
||||
num, _ := strconv.Atoi(n)
|
||||
res += num
|
||||
}
|
||||
res := 0
|
||||
dfs(root, 0, &res)
|
||||
return res
|
||||
}
|
||||
|
||||
func binaryTreeNums(root *TreeNode) []string {
|
||||
func dfs(root *TreeNode, sum int, res *int) {
|
||||
if root == nil {
|
||||
return []string{}
|
||||
return
|
||||
}
|
||||
res := []string{}
|
||||
sum = sum*10 + root.Val
|
||||
if root.Left == nil && root.Right == nil {
|
||||
return []string{strconv.Itoa(root.Val)}
|
||||
*res += sum
|
||||
return
|
||||
}
|
||||
tmpLeft := binaryTreeNums(root.Left)
|
||||
for i := 0; i < len(tmpLeft); i++ {
|
||||
res = append(res, strconv.Itoa(root.Val)+tmpLeft[i])
|
||||
}
|
||||
tmpRight := binaryTreeNums(root.Right)
|
||||
for i := 0; i < len(tmpRight); i++ {
|
||||
res = append(res, strconv.Itoa(root.Val)+tmpRight[i])
|
||||
}
|
||||
return res
|
||||
dfs(root.Left, sum, res)
|
||||
dfs(root.Right, sum, res)
|
||||
}
|
||||
|
@ -45,4 +45,4 @@ Find the total sum of all root-to-leaf numbers.
|
||||
|
||||
## 解题思路
|
||||
|
||||
- 这一题是第 257 题的变形题,第 257 题要求输出每条从根节点到叶子节点的路径,这一题变成了把每一个从根节点到叶子节点的数字都串联起来,再累加每条路径,求出最后的总和。实际做题思路基本没变
|
||||
- 运用前序遍历的思想,当从根节点出发一直加到叶子节点,每个叶子节点汇总一次。
|
20
leetcode/0135.Candy/135. Candy.go
Normal file
20
leetcode/0135.Candy/135. Candy.go
Normal file
@ -0,0 +1,20 @@
|
||||
package leetcode
|
||||
|
||||
func candy(ratings []int) int {
|
||||
candies := make([]int, len(ratings))
|
||||
for i := 1; i < len(ratings); i++ {
|
||||
if ratings[i] > ratings[i-1] {
|
||||
candies[i] += candies[i-1] + 1
|
||||
}
|
||||
}
|
||||
for i := len(ratings) - 2; i >= 0; i-- {
|
||||
if ratings[i] > ratings[i+1] && candies[i] <= candies[i+1] {
|
||||
candies[i] = candies[i+1] + 1
|
||||
}
|
||||
}
|
||||
total := 0
|
||||
for _, candy := range candies {
|
||||
total += candy + 1
|
||||
}
|
||||
return total
|
||||
}
|
47
leetcode/0135.Candy/135. Candy_test.go
Normal file
47
leetcode/0135.Candy/135. Candy_test.go
Normal file
@ -0,0 +1,47 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type question135 struct {
|
||||
para135
|
||||
ans135
|
||||
}
|
||||
|
||||
// para 是参数
|
||||
// one 代表第一个参数
|
||||
type para135 struct {
|
||||
ratings []int
|
||||
}
|
||||
|
||||
// ans 是答案
|
||||
// one 代表第一个答案
|
||||
type ans135 struct {
|
||||
one int
|
||||
}
|
||||
|
||||
func Test_Problem135(t *testing.T) {
|
||||
|
||||
qs := []question135{
|
||||
|
||||
{
|
||||
para135{[]int{1, 0, 2}},
|
||||
ans135{5},
|
||||
},
|
||||
|
||||
{
|
||||
para135{[]int{1, 2, 2}},
|
||||
ans135{4},
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Printf("------------------------Leetcode Problem 135------------------------\n")
|
||||
|
||||
for _, q := range qs {
|
||||
_, p := q.ans135, q.para135
|
||||
fmt.Printf("【input】:%v 【output】:%v\n", p, candy(p.ratings))
|
||||
}
|
||||
fmt.Printf("\n\n\n")
|
||||
}
|
74
leetcode/0135.Candy/README.md
Normal file
74
leetcode/0135.Candy/README.md
Normal file
@ -0,0 +1,74 @@
|
||||
# [135. Candy](https://leetcode.com/problems/candy/)
|
||||
|
||||
|
||||
## 题目
|
||||
|
||||
There are `n` children standing in a line. Each child is assigned a rating value given in the integer array `ratings`.
|
||||
|
||||
You are giving candies to these children subjected to the following requirements:
|
||||
|
||||
- Each child must have at least one candy.
|
||||
- Children with a higher rating get more candies than their neighbors.
|
||||
|
||||
Return *the minimum number of candies you need to have to distribute the candies to the children*.
|
||||
|
||||
**Example 1:**
|
||||
|
||||
```
|
||||
Input: ratings = [1,0,2]
|
||||
Output: 5
|
||||
Explanation: You can allocate to the first, second and third child with 2, 1, 2 candies respectively.
|
||||
```
|
||||
|
||||
**Example 2:**
|
||||
|
||||
```
|
||||
Input: ratings = [1,2,2]
|
||||
Output: 4
|
||||
Explanation: You can allocate to the first, second and third child with 1, 2, 1 candies respectively.
|
||||
The third child gets 1 candy because it satisfies the above two conditions.
|
||||
```
|
||||
|
||||
**Constraints:**
|
||||
|
||||
- `n == ratings.length`
|
||||
- `1 <= n <= 2 * 10^4`
|
||||
- `0 <= ratings[i] <= 2 * 10^4`
|
||||
|
||||
## 题目大意
|
||||
|
||||
老师想给孩子们分发糖果,有 N 个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分。你需要按照以下要求,帮助老师给这些孩子分发糖果:
|
||||
|
||||
- 每个孩子至少分配到 1 个糖果。
|
||||
- 评分更高的孩子必须比他两侧的邻位孩子获得更多的糖果。
|
||||
|
||||
那么这样下来,老师至少需要准备多少颗糖果呢?
|
||||
|
||||
## 解题思路
|
||||
|
||||
- 本题的突破口在于,评分更高的孩子必须比他两侧的邻位孩子获得更多的糖果,这句话。这个规则可以理解为 2 条规则,想象成按身高排队,站在下标为 0 的地方往后“看”,评分高即为个子高的,应该比前面个子矮(评分低)的分到糖果多;站在下标为 n - 1 的地方往后“看”,评分高即为个子高的,同样应该比前面个子矮(评分低)的分到糖果多。你可能会有疑问,规则都是一样的,为什么会出现至少需要多少糖果呢?因为可能出现评分一样高的同学。扫描数组两次,处理出每一个学生分别满足左规则或右规则时,最少需要被分得的糖果数量。每个人最终分得的糖果数量即为这两个数量的最大值。两次遍历结束,将所有糖果累加起来即为至少需要准备的糖果数。由于每个人至少分配到 1 个糖果,所以每个人糖果数再加一。
|
||||
|
||||
## 代码
|
||||
|
||||
```go
|
||||
package leetcode
|
||||
|
||||
func candy(ratings []int) int {
|
||||
candies := make([]int, len(ratings))
|
||||
for i := 1; i < len(ratings); i++ {
|
||||
if ratings[i] > ratings[i-1] {
|
||||
candies[i] += candies[i-1] + 1
|
||||
}
|
||||
}
|
||||
for i := len(ratings) - 2; i >= 0; i-- {
|
||||
if ratings[i] > ratings[i+1] && candies[i] <= candies[i+1] {
|
||||
candies[i] = candies[i+1] + 1
|
||||
}
|
||||
}
|
||||
total := 0
|
||||
for _, candy := range candies {
|
||||
total += candy + 1
|
||||
}
|
||||
return total
|
||||
}
|
||||
```
|
@ -26,4 +26,4 @@ Your algorithm should have a linear runtime complexity. Could you implement it w
|
||||
## 解题思路
|
||||
|
||||
- 题目要求不能使用辅助空间,并且时间复杂度只能是线性的。
|
||||
- 题目为什么要强调有一个数字出现一次,其他的出现两次?我们想到了异或运算的性质:任何一个数字异或它自己都等于0。也就是说,如果我们从头到尾依次异或数组中的每一个数字,那么最终的结果刚好是那个只出现依次的数字,因为那些出现两次的数字全部在异或中抵消掉了。于是最终做法是从头到尾依次异或数组中的每一个数字,那么最终得到的结果就是两个只出现一次的数字的异或结果。因为其他数字都出现了两次,在异或中全部抵消掉了。**利用的性质是 x^x = 0**。
|
||||
- 题目为什么要强调有一个数字出现一次,其他的出现两次?我们想到了异或运算的性质:任何一个数字异或它自己都等于0。也就是说,如果我们从头到尾依次异或数组中的每一个数字,那么最终的结果刚好是那个只出现一次的数字,因为那些出现两次的数字全部在异或中抵消掉了。于是最终做法是从头到尾依次异或数组中的每一个数字,那么最终得到的结果就是两个只出现一次的数字的异或结果。因为其他数字都出现了两次,在异或中全部抵消掉了。**利用的性质是 x^x = 0**。
|
||||
|
@ -30,9 +30,9 @@ Your algorithm should have a linear runtime complexity. Could you implement it w
|
||||
## 解题思路
|
||||
|
||||
- 这一题是第 136 题的加强版。这类题也可以扩展,在数组中每个元素都出现 5 次,找出只出现 1 次的数。
|
||||
- 本题中要求找出只出现 1 次的数,出现 3 次的数都要被消除。第 136 题是消除出现 2 次的数。这一题也会相当相同的解法,出现 3 次的数也要被消除。定义状态,00、10、01,这 3 个状态。当一个数出现 3 次,那么它每个位置上的 1 出现的次数肯定是 3 的倍数,所以当 1 出现 3 次以后,就归零清除。如何能做到这点呢?仿造`三进制(00,10,01)` 就可以做到。
|
||||
- 本题中要求找出只出现 1 次的数,出现 3 次的数都要被消除。第 136 题是消除出现 2 次的数。这一题也会相当相同的解法,出现 3 次的数也要被消除。定义状态,00、10、01,这 3 个状态。当一个数出现 3 次,那么它每个位置上的 1 出现的次数肯定是 3 的倍数,所以当 1 出现 3 次以后,就归零清除。如何能做到这点呢?仿造`三进制(00,01,10)` 就可以做到。
|
||||
- 变量 ones 中记录遍历中每个位上出现 1 的个数。将它与 A[i] 进行异或,目的是:
|
||||
- 每位上两者都是 1 的,表示历史统计结果 ones 出现1次、A[i]中又出现1次,则是出现 2 次,需要进位到 twos 变量中。
|
||||
- 每位上两者都是 1 的,表示历史统计结果 ones 出现1次、A[i]中又出现 1 次,则是出现 2 次,需要进位到 twos 变量中。
|
||||
- 每位上两者分别为 0、1 的,加入到 ones 统计结果中。
|
||||
- 最后还要 & ^twos ,是为了能做到三进制,出现 3 次就清零。例如 ones = x,那么 twos = 0,当 twos = x,那么 ones = 0;
|
||||
- 变量 twos 中记录遍历中每个位上出现 1 ,2次 的个数。与 A[i] 进行异或的目的和上述描述相同,不再赘述。
|
||||
@ -41,6 +41,31 @@ Your algorithm should have a linear runtime complexity. Could you implement it w
|
||||
|
||||
> 在 golang 中没有 Java 中的 ~ 位操作运算符,Java 中的 ~ 运算符代表按位取反。这个操作就想当于 golang 中的 ^ 运算符当做一元运算符使用的效果。
|
||||
|
||||
|(twos,ones)|xi|(twos'',ones')|ones'|
|
||||
|:----:|:----:|:----:|:----:|
|
||||
|00|0|00|0|
|
||||
|00|1|01|1|
|
||||
|01|0|01|1|
|
||||
|01|1|10|0|
|
||||
|10|0|10|0|
|
||||
|10|1|00|0|
|
||||
|
||||
- 第一步,先将 ones -> ones'。通过观察可以看出 ones = (ones ^ nums[i]) & ^twos
|
||||
|
||||
|(twos,ones')|xi|twos'|
|
||||
|:----:|:----:|:----:|
|
||||
|00|0|0|
|
||||
|01|1|0|
|
||||
|01|0|0|
|
||||
|00|1|1|
|
||||
|10|0|1|
|
||||
|10|1|0|
|
||||
|
||||
|
||||
- 第二步,再将 twos -> twos'。这一步需要用到前一步的 ones。通过观察可以看出 twos = (twos ^ nums[i]) & ^ones。
|
||||
|
||||
--------------------------
|
||||
|
||||
这一题还可以继续扩展,在数组中每个元素都出现 5 次,找出只出现 1 次的数。那该怎么做呢?思路还是一样的,模拟一个五进制,5 次就会消除。代码如下:
|
||||
|
||||
// 解法一
|
||||
|
@ -9,17 +9,16 @@ type ListNode = structures.ListNode
|
||||
|
||||
/**
|
||||
* Definition for singly-linked list.
|
||||
* struct ListNode {
|
||||
* int val;
|
||||
* ListNode *next;
|
||||
* ListNode(int x) : val(x), next(NULL) {}
|
||||
* };
|
||||
* type ListNode struct {
|
||||
* Val int
|
||||
* Next *ListNode
|
||||
* }
|
||||
*/
|
||||
|
||||
func hasCycle(head *ListNode) bool {
|
||||
fast := head
|
||||
slow := head
|
||||
for slow != nil && fast != nil && fast.Next != nil {
|
||||
for fast != nil && fast.Next != nil {
|
||||
fast = fast.Next.Next
|
||||
slow = slow.Next
|
||||
if fast == slow {
|
||||
|
@ -1,6 +1,54 @@
|
||||
package leetcode
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/halfrost/LeetCode-Go/structures"
|
||||
)
|
||||
|
||||
type question141 struct {
|
||||
para141
|
||||
ans141
|
||||
}
|
||||
|
||||
// para 是参数
|
||||
// one 代表第一个参数
|
||||
type para141 struct {
|
||||
one []int
|
||||
}
|
||||
|
||||
// ans 是答案
|
||||
// one 代表第一个答案
|
||||
type ans141 struct {
|
||||
one bool
|
||||
}
|
||||
|
||||
func Test_Problem141(t *testing.T) {
|
||||
|
||||
qs := []question141{
|
||||
|
||||
{
|
||||
para141{[]int{3, 2, 0, -4}},
|
||||
ans141{false},
|
||||
},
|
||||
|
||||
{
|
||||
para141{[]int{1, 2}},
|
||||
ans141{false},
|
||||
},
|
||||
|
||||
{
|
||||
para141{[]int{1}},
|
||||
ans141{false},
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Printf("------------------------Leetcode Problem 141------------------------\n")
|
||||
|
||||
for _, q := range qs {
|
||||
_, p := q.ans141, q.para141
|
||||
fmt.Printf("【input】:%v 【output】:%v\n", p, hasCycle(structures.Ints2List(p.one)))
|
||||
}
|
||||
fmt.Printf("\n\n\n")
|
||||
}
|
||||
|
@ -5,46 +5,23 @@ import (
|
||||
)
|
||||
|
||||
func evalRPN(tokens []string) int {
|
||||
if len(tokens) == 1 {
|
||||
i, _ := strconv.Atoi(tokens[0])
|
||||
return i
|
||||
}
|
||||
stack, top := []int{}, 0
|
||||
for _, v := range tokens {
|
||||
switch v {
|
||||
case "+":
|
||||
{
|
||||
sum := stack[top-2] + stack[top-1]
|
||||
stack = stack[:top-2]
|
||||
stack = append(stack, sum)
|
||||
top--
|
||||
}
|
||||
case "-":
|
||||
{
|
||||
sub := stack[top-2] - stack[top-1]
|
||||
stack = stack[:top-2]
|
||||
stack = append(stack, sub)
|
||||
top--
|
||||
}
|
||||
case "*":
|
||||
{
|
||||
mul := stack[top-2] * stack[top-1]
|
||||
stack = stack[:top-2]
|
||||
stack = append(stack, mul)
|
||||
top--
|
||||
}
|
||||
case "/":
|
||||
{
|
||||
div := stack[top-2] / stack[top-1]
|
||||
stack = stack[:top-2]
|
||||
stack = append(stack, div)
|
||||
top--
|
||||
}
|
||||
default:
|
||||
{
|
||||
i, _ := strconv.Atoi(v)
|
||||
stack = append(stack, i)
|
||||
top++
|
||||
stack := make([]int, 0, len(tokens))
|
||||
for _, token := range tokens {
|
||||
v, err := strconv.Atoi(token)
|
||||
if err == nil {
|
||||
stack = append(stack, v)
|
||||
} else {
|
||||
num1, num2 := stack[len(stack)-2], stack[len(stack)-1]
|
||||
stack = stack[:len(stack)-2]
|
||||
switch token {
|
||||
case "+":
|
||||
stack = append(stack, num1+num2)
|
||||
case "-":
|
||||
stack = append(stack, num1-num2)
|
||||
case "*":
|
||||
stack = append(stack, num1*num2)
|
||||
case "/":
|
||||
stack = append(stack, num1/num2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,13 +6,14 @@ func twoSum167(numbers []int, target int) []int {
|
||||
for i < j {
|
||||
if numbers[i]+numbers[j] == target {
|
||||
return []int{i + 1, j + 1}
|
||||
} else if numbers[i]+numbers[j] < target {
|
||||
}
|
||||
if numbers[i]+numbers[j] < target {
|
||||
i++
|
||||
} else {
|
||||
j--
|
||||
}
|
||||
}
|
||||
return []int{-1, -1}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 解法二 不管数组是否有序,空间复杂度比上一种解法要多 O(n)
|
||||
@ -20,8 +21,8 @@ func twoSum167_1(numbers []int, target int) []int {
|
||||
m := make(map[int]int)
|
||||
for i := 0; i < len(numbers); i++ {
|
||||
another := target - numbers[i]
|
||||
if _, ok := m[another]; ok {
|
||||
return []int{m[another] + 1, i + 1}
|
||||
if idx, ok := m[another]; ok {
|
||||
return []int{idx + 1, i + 1}
|
||||
}
|
||||
m[numbers[i]] = i
|
||||
}
|
@ -7,7 +7,7 @@ Given a positive integer, return its corresponding column title as appear in an
|
||||
For example:
|
||||
|
||||
```
|
||||
1 -> A
|
||||
1 -> A
|
||||
2 -> B
|
||||
3 -> C
|
||||
...
|
||||
|
@ -17,33 +17,23 @@ type TreeNode = structures.TreeNode
|
||||
*/
|
||||
|
||||
func rightSideView(root *TreeNode) []int {
|
||||
res := []int{}
|
||||
if root == nil {
|
||||
return []int{}
|
||||
return res
|
||||
}
|
||||
queue := []*TreeNode{}
|
||||
queue = append(queue, root)
|
||||
curNum, nextLevelNum, res, tmp := 1, 0, []int{}, []int{}
|
||||
for len(queue) != 0 {
|
||||
if curNum > 0 {
|
||||
node := queue[0]
|
||||
if node.Left != nil {
|
||||
queue = append(queue, node.Left)
|
||||
nextLevelNum++
|
||||
queue := []*TreeNode{root}
|
||||
for len(queue) > 0 {
|
||||
n := len(queue)
|
||||
for i := 0; i < n; i++ {
|
||||
if queue[i].Left != nil {
|
||||
queue = append(queue, queue[i].Left)
|
||||
}
|
||||
if node.Right != nil {
|
||||
queue = append(queue, node.Right)
|
||||
nextLevelNum++
|
||||
if queue[i].Right != nil {
|
||||
queue = append(queue, queue[i].Right)
|
||||
}
|
||||
curNum--
|
||||
tmp = append(tmp, node.Val)
|
||||
queue = queue[1:]
|
||||
}
|
||||
if curNum == 0 {
|
||||
res = append(res, tmp[len(tmp)-1])
|
||||
curNum = nextLevelNum
|
||||
nextLevelNum = 0
|
||||
tmp = []int{}
|
||||
}
|
||||
res = append(res, queue[n-1].Val)
|
||||
queue = queue[n:]
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
@ -1,27 +1,26 @@
|
||||
package leetcode
|
||||
|
||||
func isHappy(n int) bool {
|
||||
if n == 0 {
|
||||
return false
|
||||
}
|
||||
res := 0
|
||||
num := n
|
||||
record := map[int]int{}
|
||||
for {
|
||||
for num != 0 {
|
||||
res += (num % 10) * (num % 10)
|
||||
num = num / 10
|
||||
}
|
||||
if _, ok := record[res]; !ok {
|
||||
if res == 1 {
|
||||
return true
|
||||
for n != 1 {
|
||||
record[n] = n
|
||||
n = getSquareOfDigits(n)
|
||||
for _, previous := range record {
|
||||
if n == previous {
|
||||
return false
|
||||
}
|
||||
record[res] = res
|
||||
num = res
|
||||
res = 0
|
||||
continue
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func getSquareOfDigits(n int) int {
|
||||
squareOfDigits := 0
|
||||
temporary := n
|
||||
for temporary != 0 {
|
||||
remainder := temporary % 10
|
||||
squareOfDigits += remainder * remainder
|
||||
temporary /= 10
|
||||
}
|
||||
return squareOfDigits
|
||||
}
|
||||
|
@ -35,6 +35,16 @@ func Test_Problem202(t *testing.T) {
|
||||
para202{19},
|
||||
ans202{true},
|
||||
},
|
||||
|
||||
{
|
||||
para202{2},
|
||||
ans202{false},
|
||||
},
|
||||
|
||||
{
|
||||
para202{3},
|
||||
ans202{false},
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Printf("------------------------Leetcode Problem 202------------------------\n")
|
||||
|
@ -1,24 +1,16 @@
|
||||
package leetcode
|
||||
|
||||
func minSubArrayLen(s int, nums []int) int {
|
||||
n := len(nums)
|
||||
if n == 0 {
|
||||
return 0
|
||||
}
|
||||
left, right, res, sum := 0, -1, n+1, 0
|
||||
for left < n {
|
||||
if (right+1) < n && sum < s {
|
||||
right++
|
||||
sum += nums[right]
|
||||
} else {
|
||||
func minSubArrayLen(target int, nums []int) int {
|
||||
left, sum, res := 0, 0, len(nums)+1
|
||||
for right, v := range nums {
|
||||
sum += v
|
||||
for sum >= target {
|
||||
res = min(res, right-left+1)
|
||||
sum -= nums[left]
|
||||
left++
|
||||
}
|
||||
if sum >= s {
|
||||
res = min(res, right-left+1)
|
||||
}
|
||||
}
|
||||
if res == n+1 {
|
||||
if res == len(nums)+1 {
|
||||
return 0
|
||||
}
|
||||
return res
|
||||
|
@ -1,6 +1,9 @@
|
||||
package leetcode
|
||||
|
||||
import "sort"
|
||||
import (
|
||||
"math/rand"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// 解法一 排序,排序的方法反而速度是最快的
|
||||
func findKthLargest1(nums []int, k int) int {
|
||||
@ -9,36 +12,62 @@ func findKthLargest1(nums []int, k int) int {
|
||||
}
|
||||
|
||||
// 解法二 这个方法的理论依据是 partition 得到的点的下标就是最终排序之后的下标,根据这个下标,我们可以判断第 K 大的数在哪里
|
||||
// 时间复杂度 O(n),空间复杂度 O(log n),最坏时间复杂度为 O(n^2),空间复杂度 O(n)
|
||||
func findKthLargest(nums []int, k int) int {
|
||||
if len(nums) == 0 {
|
||||
return 0
|
||||
}
|
||||
return selection(nums, 0, len(nums)-1, len(nums)-k)
|
||||
m := len(nums) - k + 1 // mth smallest, from 1..len(nums)
|
||||
return selectSmallest(nums, 0, len(nums)-1, m)
|
||||
}
|
||||
|
||||
func selection(arr []int, l, r, k int) int {
|
||||
if l == r {
|
||||
return arr[l]
|
||||
func selectSmallest(nums []int, l, r, i int) int {
|
||||
if l >= r {
|
||||
return nums[l]
|
||||
}
|
||||
p := partition164(arr, l, r)
|
||||
if k == p {
|
||||
return arr[p]
|
||||
} else if k < p {
|
||||
return selection(arr, l, p-1, k)
|
||||
q := partition(nums, l, r)
|
||||
k := q - l + 1
|
||||
if k == i {
|
||||
return nums[q]
|
||||
}
|
||||
if i < k {
|
||||
return selectSmallest(nums, l, q-1, i)
|
||||
} else {
|
||||
return selection(arr, p+1, r, k)
|
||||
return selectSmallest(nums, q+1, r, i-k)
|
||||
}
|
||||
}
|
||||
|
||||
func partition164(a []int, lo, hi int) int {
|
||||
pivot := a[hi]
|
||||
i := lo - 1
|
||||
for j := lo; j < hi; j++ {
|
||||
if a[j] < pivot {
|
||||
func partition(nums []int, l, r int) int {
|
||||
k := l + rand.Intn(r-l+1) // 此处为优化,使得时间复杂度期望降为 O(n),最坏时间复杂度为 O(n^2)
|
||||
nums[k], nums[r] = nums[r], nums[k]
|
||||
i := l - 1
|
||||
// nums[l..i] <= nums[r]
|
||||
// nums[i+1..j-1] > nums[r]
|
||||
for j := l; j < r; j++ {
|
||||
if nums[j] <= nums[r] {
|
||||
i++
|
||||
a[j], a[i] = a[i], a[j]
|
||||
nums[i], nums[j] = nums[j], nums[i]
|
||||
}
|
||||
}
|
||||
a[i+1], a[hi] = a[hi], a[i+1]
|
||||
nums[i+1], nums[r] = nums[r], nums[i+1]
|
||||
return i + 1
|
||||
}
|
||||
|
||||
// 扩展题 剑指 Offer 40. 最小的 k 个数
|
||||
func getLeastNumbers(arr []int, k int) []int {
|
||||
return selectSmallest1(arr, 0, len(arr)-1, k)[:k]
|
||||
}
|
||||
|
||||
// 和 selectSmallest 实现完全一致,只是返回值不用再截取了,直接返回 nums 即可
|
||||
func selectSmallest1(nums []int, l, r, i int) []int {
|
||||
if l >= r {
|
||||
return nums
|
||||
}
|
||||
q := partition(nums, l, r)
|
||||
k := q - l + 1
|
||||
if k == i {
|
||||
return nums
|
||||
}
|
||||
if i < k {
|
||||
return selectSmallest1(nums, l, q-1, i)
|
||||
} else {
|
||||
return selectSmallest1(nums, q+1, r, i-k)
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user