├── Readme.md ├── 23_sort ├── main_test.go └── main.go ├── 02_palindrome ├── main.go └── main_test.go ├── 12_metrixs ├── main.go └── main_test.go ├── 15_stack ├── main_test.go └── main.go ├── 10_pyramid ├── main_test.go └── main.go ├── 14_queue ├── main_test.go └── main.go ├── 16_queue_from_stack ├── main_test.go └── main.go ├── 09_steps ├── main_test.go └── main.go ├── 08_sentence_capitalization ├── main.go └── main_test.go ├── 18_find_middle_point ├── main_test.go └── main.go ├── 20_step_back_from_tail └── main.go ├── 04_max_chars ├── main_test.go └── main.go ├── 03_reversing_an_int ├── main_test.go └── main.go ├── 05_fuzzbuzz └── main.go ├── 11_vowels ├── main_test.go └── main.go ├── 01_string_reversal ├── main_test.go └── main.go ├── 13_fibonacci ├── main_test.go └── main.go ├── 22_bst ├── main_test.go └── main.go ├── 19_circurl_list └── main.go ├── 07_anagrams ├── main_test.go └── main.go ├── 21_build_a_tree ├── main_test.go └── main.go ├── 06_array_chunk └── main.go └── 17_linked_list ├── main_test.go └── main.go /Readme.md: -------------------------------------------------------------------------------- 1 | # Golang Coding Interview Q&A 2 | 3 | golang 代码面试的问题与答案 4 | 5 | 结合[Udmey高分课程](https://www.udemy.com/coding-interview-bootcamp-algorithms-and-data-structure/learn/v4/overview)的学习路线 -------------------------------------------------------------------------------- /23_sort/main_test.go: -------------------------------------------------------------------------------- 1 | package _3_sort 2 | 3 | import "testing" 4 | 5 | func TestSort(t *testing.T) { 6 | raw := []int{2, 31, 3, 4, 5, 12, 3, 4, 3, 8, 54, 1, 531241, 676} 7 | t.Log(BubbleSort(raw)) 8 | t.Log(SelectSort(raw)) 9 | t.Log(MergeSort(raw)) 10 | } 11 | -------------------------------------------------------------------------------- /02_palindrome/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // check 用于检验字符串是否满足回文的要求 4 | // 可以借鉴对应 5 | func check(str string) bool { 6 | runes := []rune(str) 7 | for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 { 8 | if runes[i] != runes[j] { 9 | return false 10 | } 11 | } 12 | return true 13 | } 14 | -------------------------------------------------------------------------------- /12_metrixs/main.go: -------------------------------------------------------------------------------- 1 | package _2_metrixs 2 | 3 | // 12_metrixs 输入一个整数n, 输出一个n*n的矩阵 4 | 5 | func matrix(num int) (metrixs [][]int) { 6 | for i := 0; i < num; i++ { 7 | var line []int 8 | for j := 1; j <= num; j++ { 9 | line = append(line, i*num+j) 10 | } 11 | metrixs = append(metrixs, line) 12 | } 13 | return 14 | } 15 | -------------------------------------------------------------------------------- /15_stack/main_test.go: -------------------------------------------------------------------------------- 1 | package _5_stack 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func Test(t *testing.T) { 9 | s := new(stack) 10 | s.Push(1) 11 | s.Push(12) 12 | s.Push(123) 13 | fmt.Println(s) 14 | fmt.Println(s.Pop()) 15 | fmt.Println(s) 16 | fmt.Println(s.Pop()) 17 | fmt.Println(s) 18 | fmt.Println(s.Pop()) 19 | } 20 | -------------------------------------------------------------------------------- /10_pyramid/main_test.go: -------------------------------------------------------------------------------- 1 | package _0_pyramid 2 | 3 | import "testing" 4 | 5 | func Test(t *testing.T) { 6 | testcases := []struct { 7 | num int 8 | }{ 9 | {2}, 10 | {3}, 11 | {5}, 12 | } 13 | 14 | getResult := func(do func(int)) { 15 | for _, testcase := range testcases { 16 | do(testcase.num) 17 | } 18 | } 19 | 20 | getResult(pyamid) 21 | } 22 | -------------------------------------------------------------------------------- /14_queue/main_test.go: -------------------------------------------------------------------------------- 1 | package _4_queue 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func Test(t *testing.T) { 9 | q := new(queue) 10 | q.Enqueue(1) 11 | q.Enqueue(12) 12 | q.Enqueue(123) 13 | fmt.Println(q) 14 | fmt.Println(q.Dequeue()) 15 | fmt.Println(q) 16 | fmt.Println(q.Dequeue()) 17 | fmt.Println(q) 18 | fmt.Println(q.Dequeue()) 19 | } 20 | -------------------------------------------------------------------------------- /16_queue_from_stack/main_test.go: -------------------------------------------------------------------------------- 1 | package _6_queue_from_stack 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func Test(t *testing.T) { 9 | q := NewQueue() 10 | q.Add(1) 11 | q.Add(12) 12 | q.Add(123) 13 | fmt.Println(q) 14 | fmt.Println(q.Remove()) 15 | fmt.Println(q) 16 | fmt.Println(q.Remove()) 17 | fmt.Println(q) 18 | fmt.Println(q.Remove()) 19 | } 20 | -------------------------------------------------------------------------------- /09_steps/main_test.go: -------------------------------------------------------------------------------- 1 | package _9_steps 2 | 3 | import "testing" 4 | 5 | func Test(t *testing.T) { 6 | testcases := []struct { 7 | num int 8 | }{ 9 | {2}, 10 | {3}, 11 | {5}, 12 | } 13 | 14 | getResult := func(do func(int)) { 15 | for _, testcase := range testcases { 16 | do(testcase.num) 17 | } 18 | } 19 | 20 | getResult(steps) 21 | 22 | getResult(stepsRecusive) 23 | } 24 | -------------------------------------------------------------------------------- /08_sentence_capitalization/main.go: -------------------------------------------------------------------------------- 1 | package _8_sentence_capitalization 2 | 3 | import "strings" 4 | 5 | // 将一个句子中的每一个词的首字母大写 6 | 7 | func c(str string) string { 8 | ss := strings.Split(str, "") 9 | for index, _ := range ss { 10 | if index == 0 || ss[index-1] == " " || ss[index-1] == "," { 11 | if ss[index][0] <= 'z' { 12 | ss[index] = strings.ToUpper(ss[index]) 13 | } 14 | } 15 | } 16 | return strings.Join(ss, "") 17 | } 18 | -------------------------------------------------------------------------------- /18_find_middle_point/main_test.go: -------------------------------------------------------------------------------- 1 | package _8_find_middle_point 2 | 3 | import ( 4 | "fmt" 5 | "golang-coding-interview-questions-and-solutions/17_linked_list" 6 | "testing" 7 | ) 8 | 9 | func Test(t *testing.T) { 10 | list := linked_list.NewLinkedList() 11 | list.InsertFirst(1) 12 | list.InsertFirst(2) 13 | list.InsertFirst(3) 14 | list.InsertFirst(4) 15 | 16 | // list : 4 > 3 > 2 > 1 17 | 18 | fmt.Println(middle(list)) 19 | } 20 | -------------------------------------------------------------------------------- /15_stack/main.go: -------------------------------------------------------------------------------- 1 | package _5_stack 2 | 3 | import "errors" 4 | 5 | type Stack interface { 6 | Push(i int) 7 | Pop() (i int, err error) 8 | } 9 | 10 | type stack struct { 11 | slice []int 12 | } 13 | 14 | func (s *stack) Push(i int) { 15 | s.slice = append(s.slice, i) 16 | } 17 | 18 | func (s *stack) Pop() (i int, err error) { 19 | if len(s.slice) == 0 { 20 | return i, errors.New("no int in stack") 21 | } 22 | i = s.slice[len(s.slice)-1] 23 | s.slice = s.slice[:len(s.slice)-1] 24 | return 25 | } 26 | -------------------------------------------------------------------------------- /20_step_back_from_tail/main.go: -------------------------------------------------------------------------------- 1 | package _0_step_back_from_tail 2 | 3 | import "golang-coding-interview-questions-and-solutions/17_linked_list" 4 | 5 | // 找到距离tail n 个位置的节点 6 | // 最直觉的算法是通过,size,但是,如果不用size呢? 7 | // 很漂亮的算法,fast先行 8 | 9 | func StepBack(head *linked_list.Node, num int) *linked_list.Node { 10 | fast, slow := head, head 11 | for i := 0; i < num; i++ { 12 | fast = fast.Next 13 | } 14 | for fast.Next != nil { 15 | fast = fast.Next 16 | slow = slow.Next 17 | } 18 | return slow 19 | } 20 | -------------------------------------------------------------------------------- /04_max_chars/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "testing" 4 | 5 | func Test(t *testing.T) { 6 | testcases := []struct { 7 | str string 8 | result string 9 | }{ 10 | {"Hello There?", "e"}, 11 | {"11122334", "1"}, 12 | } 13 | 14 | getResult := func(do func(str string) string) { 15 | for _, testcase := range testcases { 16 | if testcase.result != do(testcase.str) { 17 | t.Error("except", testcase.result, "get", do(testcase.str)) 18 | } 19 | } 20 | } 21 | 22 | getResult(maxChars) 23 | } 24 | -------------------------------------------------------------------------------- /02_palindrome/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "testing" 4 | 5 | func Test(t *testing.T) { 6 | testcases := []struct { 7 | str1 string 8 | result bool 9 | }{ 10 | {"hello", false}, 11 | {"abba", true}, 12 | {"世界界世", true}, 13 | } 14 | 15 | getResult := func(do func(str1 string) bool) { 16 | for _, testcase := range testcases { 17 | if testcase.result != do(testcase.str1) { 18 | t.Error("except", testcase.result, "get", do(testcase.str1)) 19 | } 20 | } 21 | } 22 | 23 | getResult(check) 24 | } 25 | -------------------------------------------------------------------------------- /03_reversing_an_int/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "testing" 4 | 5 | func Test(t *testing.T) { 6 | testcases := []struct { 7 | num int 8 | result int 9 | }{ 10 | {10032, 23001}, 11 | {-11003223001, -10032230011}, 12 | {-90, -9}, 13 | } 14 | 15 | getResult := func(do func(num int) int) { 16 | for _, testcase := range testcases { 17 | if testcase.result != do(testcase.num) { 18 | t.Error("except", testcase.result, "get", do(testcase.num)) 19 | } 20 | } 21 | } 22 | 23 | getResult(P) 24 | getResult(P2) 25 | } 26 | -------------------------------------------------------------------------------- /05_fuzzbuzz/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // fuzzbuzz问题: 6 | // 输入一个整数 7 | // 找出其中的fuzz数,3的倍数 8 | // 找出其中的buzz数,5的倍数 9 | 10 | // 号称是面试中,经常出现的最简单题 11 | // 对应leetcode 412 12 | 13 | func main() { 14 | fuzzbuzz(15) 15 | } 16 | 17 | func fuzzbuzz(num int) { 18 | for i:=1; i <= num ; i ++ { 19 | switch { 20 | case i%3 == 0 && i%5 == 0 : 21 | fmt.Println("fizzbuzz") 22 | case i%3 == 0: 23 | fmt.Println("fizz") 24 | case i%5 == 0: 25 | fmt.Println("buzz") 26 | default: 27 | fmt.Println(i) 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /11_vowels/main_test.go: -------------------------------------------------------------------------------- 1 | package _1_vowels 2 | 3 | import "testing" 4 | 5 | func Test(t *testing.T) { 6 | testcases := []struct { 7 | str string 8 | num int 9 | }{ 10 | {"Hi There!", 3}, 11 | {"Why do you ask?", 4}, 12 | {"Why?!", 0}, 13 | } 14 | 15 | getResult := func(do func(string) int) { 16 | for _, testcase := range testcases { 17 | if testcase.num != do(testcase.str) { 18 | t.Errorf("except %d get %d", testcase.num, do(testcase.str)) 19 | } 20 | } 21 | } 22 | 23 | getResult(vowels) 24 | 25 | getResult(vowelsReg) 26 | } 27 | -------------------------------------------------------------------------------- /12_metrixs/main_test.go: -------------------------------------------------------------------------------- 1 | package _2_metrixs 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func Test(t *testing.T) { 8 | testcases := []struct { 9 | num int 10 | metrixs [][]int 11 | }{ 12 | {2, [][]int{{1, 2}, {3, 4}}}, 13 | {3, [][]int{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}, 14 | {4, [][]int{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}}}, 15 | } 16 | 17 | getResult := func(do func(int) [][]int) { 18 | for _, testcase := range testcases { 19 | t.Logf("%#v\n", do(testcase.num)) 20 | } 21 | } 22 | 23 | getResult(matrix) 24 | } 25 | -------------------------------------------------------------------------------- /18_find_middle_point/main.go: -------------------------------------------------------------------------------- 1 | package _8_find_middle_point 2 | 3 | import "golang-coding-interview-questions-and-solutions/17_linked_list" 4 | 5 | // 链表常用方法: 6 | // fast,show point 7 | // fast 到终点, show 刚好跑一半 8 | func middle(ls *linked_list.LinkedList) (data interface{}) { 9 | head := ls.Head() 10 | if head == nil { 11 | return nil 12 | } 13 | 14 | fast, show := head, head 15 | 16 | // fast 一次移动2步,show 一次移动1步 17 | for fast.Next != nil && fast.Next.Next != nil { 18 | fast = fast.Next.Next 19 | show = show.Next 20 | } 21 | 22 | return show.Data 23 | } 24 | -------------------------------------------------------------------------------- /01_string_reversal/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "testing" 4 | 5 | func Test(t *testing.T) { 6 | testcases := []struct { 7 | str1 string 8 | str2 string 9 | }{ 10 | {"cda54321", "12345adc"}, 11 | {"hello 世界", "界世 olleh"}, 12 | } 13 | 14 | getResult := func(do func(str1 string) string) { 15 | for _, testcase := range testcases { 16 | if testcase.str2 != do(testcase.str1) { 17 | t.Error("except", testcase.str2, "get", do(testcase.str1)) 18 | } 19 | } 20 | } 21 | 22 | getResult(reverse02) 23 | 24 | getResult(reverseByByte) 25 | } 26 | -------------------------------------------------------------------------------- /13_fibonacci/main_test.go: -------------------------------------------------------------------------------- 1 | package _3_fibonacci 2 | 3 | import "testing" 4 | 5 | func Test(t *testing.T) { 6 | testcases := []struct { 7 | num int 8 | fnum int 9 | }{ 10 | {2, 1}, 11 | {3, 2}, 12 | {6, 8}, 13 | } 14 | 15 | getResult := func(do func(int) int) { 16 | for _, testcase := range testcases { 17 | if testcase.fnum != do(testcase.num) { 18 | t.Error("except", testcase.fnum, "get", do(testcase.num)) 19 | } 20 | } 21 | } 22 | 23 | getResult(fibonacciIterative) 24 | getResult(fibonacciRecusive) 25 | getResult(fibonacciRecusiveMem) 26 | } 27 | -------------------------------------------------------------------------------- /22_bst/main_test.go: -------------------------------------------------------------------------------- 1 | package _2_bst 2 | 3 | import "testing" 4 | 5 | func TestBSTTree_Search(t *testing.T) { 6 | tree := NewBSTTree() 7 | tree.Add(10) 8 | tree.Add(0) 9 | tree.Add(12) 10 | tree.Add(-1) 11 | tree.Add(11) 12 | t.Log(tree.Search(-1) == true) 13 | t.Log(tree.Search(-2) == false) 14 | t.Log(tree.Search(12) == true) 15 | } 16 | 17 | func TestNewBSTNode(t *testing.T) { 18 | t1 := TreeNode{ 19 | Val: 1, 20 | } 21 | t3 := TreeNode{ 22 | Val: 3, 23 | } 24 | t2 := TreeNode{ 25 | Val: 2, 26 | Left: &t1, 27 | Right: &t3, 28 | } 29 | t.Log(validBST(&t2, nil, nil)) 30 | } 31 | -------------------------------------------------------------------------------- /08_sentence_capitalization/main_test.go: -------------------------------------------------------------------------------- 1 | package _8_sentence_capitalization 2 | 3 | import "testing" 4 | 5 | func Test(t *testing.T) { 6 | testcases := []struct { 7 | str1 string 8 | str2 string 9 | }{ 10 | {"anagram", "Anagram"}, 11 | {"rat,hello", "Rat,Hello"}, 12 | {"rail safety", "Rail Safety"}, 13 | } 14 | 15 | getResult := func(do func(string) string) { 16 | for _, testcase := range testcases { 17 | if testcase.str2 != do(testcase.str1) { 18 | t.Error(testcase.str1, testcase.str2, "except", testcase.str2, "get", do(testcase.str1)) 19 | } 20 | } 21 | } 22 | 23 | getResult(c) 24 | } 25 | -------------------------------------------------------------------------------- /19_circurl_list/main.go: -------------------------------------------------------------------------------- 1 | package _9_circurl_list 2 | 3 | import ( 4 | "golang-coding-interview-questions-and-solutions/17_linked_list" 5 | ) 6 | 7 | // 检测一个链表是否成环 loop 8 | // 对应 两道 leetcode 的题,题号 141 , 142 9 | // 这个也是典型的要使用fast,slow指针的问题 10 | 11 | // fast遇到null ,则表示无环 12 | // fast遇到slow,则表示有环 13 | 14 | // leetCode 8ms 15 | func DelectLoop(node *linked_list.Node) bool { 16 | if node == nil || node.Next == nil { 17 | return false 18 | } 19 | slow, fast := node, node 20 | for fast.Next != nil && fast.Next.Next != nil { 21 | fast = fast.Next.Next 22 | slow = slow.Next 23 | if fast == slow { 24 | return true 25 | } 26 | } 27 | return false 28 | } 29 | -------------------------------------------------------------------------------- /04_max_chars/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // max chars : 找到一个字符串中,数量最多的那一个字符 4 | // 遇到字符串相关的算法,首先要问自己3个问题: 5 | // 1. 字符串中最常见的字符是什么? 6 | // 2. 输入和输出的字符串有相同的字符吗? 7 | // 3. 给出的字符串中有重复的字符吗? 8 | 9 | // 使用map 10 | func maxChars(str string) string { 11 | bytesMap := make(map[byte]int) 12 | bs := []byte(str) 13 | if len(bs) == 0 { 14 | return "" 15 | } 16 | 17 | var maxchar byte = 0 18 | maxcount := 0 19 | for _, b := range bs { 20 | count := bytesMap[b] 21 | bytesMap[b] = count + 1 22 | // 判断当前的字符是否大于当前最大 23 | if bytesMap[b] > maxcount { 24 | maxchar = b 25 | maxcount = bytesMap[b] 26 | } 27 | } 28 | 29 | return string([]byte{maxchar}) 30 | } 31 | -------------------------------------------------------------------------------- /07_anagrams/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "testing" 4 | 5 | func Test(t *testing.T) { 6 | testcases := []struct { 7 | str1 string 8 | str2 string 9 | result bool 10 | }{ 11 | {"anagram", "nagaram", true}, 12 | {"rat", "car", false}, 13 | {"rail safety", "fairy tales", true}, 14 | } 15 | 16 | getResult := func(isanagram func(str1, str2 string) bool) { 17 | for _, testcase := range testcases { 18 | if testcase.result != isanagram(testcase.str1, testcase.str2) { 19 | t.Error(testcase.str1, testcase.str2, "except", testcase.result, "get", !testcase.result) 20 | } 21 | } 22 | } 23 | 24 | getResult(anagram) 25 | 26 | getResult(anagram2) 27 | } 28 | -------------------------------------------------------------------------------- /10_pyramid/main.go: -------------------------------------------------------------------------------- 1 | package _0_pyramid 2 | 3 | import "fmt" 4 | 5 | // 和上一个阶梯类似,输出金字塔型的# 6 | // 例如输出3 7 | // " # " 8 | // " ### " 9 | // "#####" 10 | 11 | // 首当其冲就是递归 12 | // 用递归,每一层和每一层之间的关系非常清晰 13 | // 比迭代要简单的多 14 | func pyamid(n int) { 15 | // 最底层的#数 16 | printPy(n*2-1, 0) 17 | } 18 | 19 | // i = # 数量 20 | // j = 每边的数量 21 | func printPy(i, j int) { 22 | if i <= 0 { 23 | return 24 | } 25 | printPy(i-2, j+1) // 每天上一层,#数量减少2,空格数量每边加1 26 | for index := 0; index < j; index++ { 27 | fmt.Print(" ") 28 | } 29 | for index := 0; index < i; index++ { 30 | fmt.Print("#") 31 | } 32 | for index := 0; index < j; index++ { 33 | fmt.Print(" ") 34 | } 35 | fmt.Println("") 36 | } 37 | -------------------------------------------------------------------------------- /03_reversing_an_int/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "strconv" 5 | ) 6 | 7 | // 转化为字符串后,通过字符串的回文判断方法 8 | func P(num int) int { 9 | str := strconv.Itoa(num) 10 | runes := []rune(str) 11 | 12 | // 去掉负号 13 | if num < 0 { 14 | runes = runes[1:] 15 | } 16 | 17 | // 转化回文 18 | for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 { 19 | runes[i], runes[j] = runes[j], runes[i] 20 | } 21 | newNum, _ := strconv.Atoi(string(runes)) 22 | 23 | // 添加负号 24 | if num < 0 { 25 | newNum = -newNum 26 | } 27 | return newNum 28 | } 29 | 30 | // 直接对不同的位数进行判断 31 | func P2(num int) (newNum int) { 32 | for num != 0 { 33 | temp := newNum*10 + num%10 34 | if temp/10 != newNum { 35 | return 0 // 溢出 36 | } 37 | newNum, num = temp, num/10 38 | } 39 | return 40 | } 41 | -------------------------------------------------------------------------------- /09_steps/main.go: -------------------------------------------------------------------------------- 1 | package _9_steps 2 | 3 | import "fmt" 4 | 5 | // 输入一个整数n 6 | // 输出用 # 和 表示的阶梯 7 | // 比如 输入3 8 | // '# ' 9 | // "## " 10 | // "###" 11 | func steps(n int) { 12 | // 矩阵相关的先考虑一下横列之间的关系 13 | for i := 0; i < n; i++ { 14 | for j := 0; j < n; j++ { 15 | if j <= i { // 当列大于行的时候,就打应# 16 | fmt.Print("#") 17 | } else { 18 | fmt.Print(" ") 19 | } 20 | } 21 | fmt.Println("") 22 | } 23 | } 24 | 25 | // 递归的写 26 | // 这可能时史上最简单的递归的应用了 27 | func stepsRecusive(n int) { 28 | printNumbers(n, 0) 29 | } 30 | 31 | func printNumbers(i, j int) { 32 | if i == 0 { 33 | return 34 | } 35 | // 输出少一个# ,多个 36 | printNumbers(i-1, j+1) 37 | for index := 0; index < i; index++ { 38 | fmt.Print("#") 39 | } 40 | for index := 0; index < j; index++ { 41 | fmt.Print(" ") 42 | } 43 | fmt.Println("") 44 | } 45 | -------------------------------------------------------------------------------- /14_queue/main.go: -------------------------------------------------------------------------------- 1 | package _4_queue 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | ) 7 | 8 | // 队列 9 | // 面试中有可能会问到,如何用golang实现一个队列 10 | // 要实现队列,首先要指导队列是什么? 11 | // 表现特征:FIFO 12 | // 含有的方法: Enqueue , Dequeue 13 | // 下面实现一个 int 的 queue 14 | 15 | type Queue interface { 16 | // 将 i 添加到 队尾 17 | Enqueue(i int) 18 | // 返回队首的i, 如果队空,则返回error 19 | Dequeue() (i int, err error) 20 | } 21 | 22 | type queue struct { 23 | slice []int 24 | } 25 | 26 | func (q *queue) Enqueue(i int) { 27 | q.slice = append(q.slice, i) 28 | } 29 | 30 | func (q *queue) Dequeue() (i int, err error) { 31 | if len(q.slice) == 0 { 32 | return 0, errors.New("no int in queue") 33 | } 34 | // 获取队首 35 | i = q.slice[0] 36 | // 删除队首 37 | q.slice = q.slice[1:] 38 | return 39 | } 40 | 41 | func (q *queue) String() string { 42 | return fmt.Sprintf("%#v", q.slice) 43 | } 44 | -------------------------------------------------------------------------------- /01_string_reversal/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // 遍历字符串 4 | // golang 中没有build-in的例如js中的 reverse()的方法对数组进行反转,所以得手写一个反转数组的方法 5 | // 为什么这里使用了 rune ,而不是 byte ? 6 | // byte 是 8bit 7 | // rune 是 32bit 8 | // 在utf-8编码中,对于 中文字符 而言,一个字符占 3个字节, 使用 byte 是放不下的 9 | // 常见的 range 也是对str进行了隐式的 unicode 解码, 而 str[i] 并不一定和我们看到的字符串对应 10 | // 同理,如果只是序列化和反序列化,可以通过byte进行操作,但是如果涉及字符串中的反转,截断等操作,则使用rune 11 | func reverse02(str string) string { 12 | runes := []rune(str) 13 | for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 { 14 | runes[i], runes[j] = runes[j], runes[i] 15 | } 16 | return string(runes) 17 | } 18 | 19 | // 使用byte进行反转字符串的话,仅会对字母和数字有效,一旦加入中文字符串,结果就无法满足预期了 20 | func reverseByByte(str string) string { 21 | bs := []byte(str) 22 | for i, j := 0, len(str)-1; i < j; i, j = i+1, j-1 { 23 | bs[i], bs[j] = bs[j], bs[i] 24 | } 25 | return string(bs) 26 | } 27 | -------------------------------------------------------------------------------- /11_vowels/main.go: -------------------------------------------------------------------------------- 1 | package _1_vowels 2 | 3 | import ( 4 | "fmt" 5 | "regexp" 6 | "strings" 7 | ) 8 | 9 | // 获取一句话中所有的元音字母的数量 10 | // 最简单的方式就是遍历字符串中的所有字节,对每一个进行判断是否在a,e,i,o,u之中 11 | // 复杂的方式为,通过正则表达式取匹配 12 | 13 | func vowels(str string) (num int) { 14 | var vowelsmap = make(map[rune]struct{}) 15 | vowelsmap['a'] = struct{}{} 16 | vowelsmap['e'] = struct{}{} 17 | vowelsmap['i'] = struct{}{} 18 | vowelsmap['o'] = struct{}{} 19 | vowelsmap['u'] = struct{}{} 20 | str = strings.ToLower(str) 21 | for _, s := range str { 22 | if _, ok := vowelsmap[s]; ok { 23 | num++ 24 | } 25 | } 26 | return 27 | } 28 | 29 | // reg 正则表达式 30 | func vowelsReg(str string) (num int) { 31 | r, err := regexp.Compile(`[aeiou]`) 32 | if err != nil { 33 | fmt.Println(err) 34 | return 35 | } 36 | return len(r.FindAllString(strings.ToLower(str), -1)) 37 | } 38 | -------------------------------------------------------------------------------- /07_anagrams/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "sort" 5 | "strings" 6 | ) 7 | 8 | // anagram 是指,两个字符串中,如果字符的数量相同,则是 anagram 如果不同,则不是 9 | // 对应leetCode 242 10 | 11 | // 使用map对str1和str2中的不同字节进行计数 12 | // 对 str1 进行加 13 | // 对 str2 进行减 14 | func anagram(s, t string) (result bool) { 15 | m := make(map[rune]int) 16 | runes1 := []rune(s) 17 | runes2 := []rune(t) 18 | 19 | if len(runes1) != len(runes2) { 20 | return false 21 | } 22 | 23 | length := len(runes1) 24 | for i := 0; i < length; i++ { 25 | m[runes1[i]] += 1 26 | m[runes2[i]] -= 1 27 | } 28 | 29 | for _, c := range m { 30 | if c != 0 { 31 | return false 32 | } 33 | } 34 | 35 | return true 36 | } 37 | 38 | // anagram 等同于 排序后完全一样 39 | func anagram2(s, t string) bool { 40 | return stringSort(s) == stringSort(t) 41 | } 42 | 43 | func stringSort(s string) string { 44 | ss := strings.Split(s, "") 45 | sort.Strings(ss) 46 | return strings.Join(ss, "") 47 | } 48 | -------------------------------------------------------------------------------- /21_build_a_tree/main_test.go: -------------------------------------------------------------------------------- 1 | package _1_build_a_tree 2 | 3 | import "testing" 4 | 5 | func TestTree_BFS(t *testing.T) { 6 | tree := NewTree() 7 | tree.Root = NewNode(1) 8 | tree.Root.Add(2) 9 | tree.Root.Add(3) 10 | tree.Root.Children[2].Add(4) 11 | tree.Root.Children[2].Add(5) 12 | tree.Root.Children[2].Add(6) 13 | tree.Root.Children[3].Add(7) 14 | tree.Root.Children[2].Children[4].Add(8) 15 | // 1 16 | // 2 3 17 | // 466 7 18 | // 8 19 | if tree.BFS(9) == true { 20 | t.Error("no 9") 21 | } 22 | if tree.BFS(2) == false { 23 | t.Error("has 2") 24 | } 25 | } 26 | 27 | func TestTree_DFS(t *testing.T) { 28 | tree := NewTree() 29 | tree.Root = NewNode(1) 30 | tree.Root.Add(2) 31 | tree.Root.Add(3) 32 | tree.Root.Children[2].Add(4) 33 | tree.Root.Children[2].Add(5) 34 | tree.Root.Children[2].Add(6) 35 | tree.Root.Children[3].Add(7) 36 | tree.Root.Children[2].Children[4].Add(8) 37 | // 1 38 | // 2 3 39 | // 466 7 40 | // 8 41 | if tree.DFS(9) == true { 42 | t.Error("no 9") 43 | } 44 | if tree.DFS(2) == false { 45 | t.Error("has 2") 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /13_fibonacci/main.go: -------------------------------------------------------------------------------- 1 | package _3_fibonacci 2 | 3 | // fibonacci 数列对于理解时间复杂度,非常的典型,非常重要的一道题 4 | // 什么是 斐波那契数列? 0,1,1,2,3,5,8 ... 除了第一个和第二个数以外,剩下的数都满足 f(n) = f(n-2)+f(n-1) 5 | // 以下有三种解法需要掌握 6 | // 遍历,递归,优化的递归,矩阵 7 | // 输入 num 代表数列中的第num个数, 第0个数是0,第一个数是1,第二个数是1 ... 8 | // 输出 fnum 9 | 10 | // 递归的方式 - 时间复杂度 O(2^n) 11 | func fibonacciRecusive(num int) int { 12 | if num == 1 || num == 2 { 13 | return 1 14 | } 15 | return fibonacciRecusive(num-1) + fibonacciRecusive(num-2) 16 | } 17 | 18 | // 通过缓存已经计算好的结果,然后直接返回,时间复杂度可以优化到 O(n) 19 | var resultMap = make(map[int]int) 20 | 21 | func fibonacciRecusiveMem(num int) int { 22 | if result, ok := resultMap[num]; ok { 23 | return result 24 | } 25 | if num == 1 || num == 2 { 26 | return 1 27 | } 28 | result := fibonacciRecusive(num-1) + fibonacciRecusive(num-2) 29 | resultMap[num] = result 30 | return result 31 | } 32 | 33 | // 遍历的方式 - 时间复杂度 O(n) 34 | func fibonacciIterative(num int) int { 35 | var f = []int{ 36 | 0, 1, 37 | } 38 | 39 | for i := 2; i <= num; i++ { 40 | f = append(f, f[i-1]+f[i-2]) 41 | } 42 | 43 | return f[num] 44 | } 45 | 46 | // todo 使用二维矩阵的方式来将时间复杂度优化到 O(logn) 47 | func fibonacciMaxtrix(num int) int { 48 | return 0 49 | } 50 | -------------------------------------------------------------------------------- /06_array_chunk/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | // array Chunk 用于将一个长的数组,拆分为多个小的数组 8 | 9 | func main() { 10 | var intArray []int = []int{ 11 | 1, 2, 3, 4, 5, 12 | } 13 | intGroup := arrayChunk(intArray, 2) 14 | for _, intarray := range intGroup { 15 | fmt.Printf("%#v\n", intarray) 16 | } 17 | intGroup2 := arrayChunk2(intArray, 2) 18 | for _, intarray := range intGroup2 { 19 | fmt.Printf("%#v\n", intarray) 20 | } 21 | } 22 | 23 | // solution_1 先组成一个子array,再添加到整个group中 24 | func arrayChunk(intarray []int, chunk int) (result [][]int) { 25 | arrayLength := len(intarray) 26 | tempArray := []int{} 27 | for i := 1; i <= arrayLength; i++ { 28 | tempArray = append(tempArray, i) 29 | if i%chunk == 0 { 30 | result = append(result, tempArray) 31 | tempArray = []int{} 32 | } 33 | } 34 | result = append(result, tempArray) 35 | return 36 | } 37 | 38 | // solution_better 先给整个的group添加array,再像 array 中添加item 39 | func arrayChunk2(intarray []int, chunk int) (result [][]int) { 40 | for i, num := range intarray { 41 | if i%chunk == 0 || len(result) == 0 { // 只有当result为空,或者是达到要增加array的上限时,才增加一个array 42 | result = append(result, []int{}) 43 | } 44 | result[len(result)-1] = append(result[len(result)-1], num) // 给 result 的最后一个array添加 item 45 | } 46 | return 47 | } 48 | -------------------------------------------------------------------------------- /21_build_a_tree/main.go: -------------------------------------------------------------------------------- 1 | package _1_build_a_tree 2 | 3 | import "container/list" 4 | 5 | // 能写出一个tree 6 | // 能写出一个深度遍历 7 | 8 | type Node struct { 9 | Data int // 为了简化起见,这里就用 int 类型了 10 | Children map[int]*Node // 使用map,为了方便删除 11 | } 12 | 13 | func NewNode(data int) *Node { 14 | return &Node{ 15 | Data: data, 16 | Children: make(map[int]*Node), 17 | } 18 | } 19 | 20 | func (n *Node) Add(data int) { 21 | node := NewNode(data) 22 | n.Children[data] = node 23 | } 24 | 25 | func (n *Node) Remove(data int) { 26 | delete(n.Children, data) 27 | } 28 | 29 | type Tree struct { 30 | Root *Node 31 | } 32 | 33 | func NewTree() *Tree { 34 | return &Tree{ 35 | Root: nil, 36 | } 37 | } 38 | 39 | // Breadth First 根据出生的时间 40 | // 如果你要返回每一层的节点数,则需要使用BFS 41 | // BF 要用到 queue FIFO 42 | func (t *Tree) BFS(data int) bool { 43 | l := list.New() 44 | l.PushBack(t.Root) 45 | for l.Len() != 0 { 46 | front := l.Front() 47 | if front.Value.(*Node).Data == data { 48 | return true 49 | } 50 | for _, node := range front.Value.(*Node).Children { 51 | l.PushBack(node) 52 | } 53 | l.Remove(front) 54 | } 55 | return false 56 | } 57 | 58 | // Depth Frist 根据深度 59 | // DF 则要想到 递归 60 | func (t *Tree) DFS(data int) bool { 61 | return search(t.Root, data) 62 | } 63 | 64 | func search(node *Node, data int) bool { 65 | // 叶子 66 | if node.Data == data { 67 | return true 68 | } 69 | // 非叶子 70 | var result bool 71 | for _, child := range node.Children { 72 | result = result || search(child, data) 73 | } 74 | return result 75 | } 76 | -------------------------------------------------------------------------------- /16_queue_from_stack/main.go: -------------------------------------------------------------------------------- 1 | package _6_queue_from_stack 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | ) 7 | 8 | type Queue interface { 9 | // 将 i 添加到 队尾 10 | Add(i int) 11 | // 返回队首的i, 如果队空,则返回error 12 | Remove() (i int, err error) 13 | } 14 | 15 | type Stack interface { 16 | Push(i int) 17 | Pop() (i int, err error) 18 | } 19 | 20 | type stack struct { 21 | slice []int 22 | } 23 | 24 | func (s *stack) Push(i int) { 25 | s.slice = append(s.slice, i) 26 | } 27 | 28 | func (s *stack) Pop() (i int, err error) { 29 | if len(s.slice) == 0 { 30 | return i, errors.New("no int in stack") 31 | } 32 | i = s.slice[len(s.slice)-1] 33 | s.slice = s.slice[:len(s.slice)-1] 34 | return 35 | } 36 | 37 | // queue from stack 是一个通过 stack 模拟 queue 中FIFO表现的队列 38 | // 两个stack , 一个负责存, 一个负责取(关键) 39 | // 通过画图,能更好的理解这些抽象的东西,具象化这些东西,直到养成脑内画图的习惯 40 | type queueFromStack struct { 41 | fs *stack // 负责存的 42 | ss *stack // 负责取的 43 | } 44 | 45 | func NewQueue() *queueFromStack { 46 | return &queueFromStack{ 47 | fs: new(stack), 48 | ss: new(stack), 49 | } 50 | } 51 | 52 | func (q *queueFromStack) Add(i int) { 53 | q.fs.Push(i) 54 | } 55 | 56 | // 这一步是O(n)的时间复杂度 57 | func (q *queueFromStack) Remove() (ret int, err error) { 58 | for { 59 | pop, _ := q.fs.Pop() 60 | // 取走队尾 61 | if len(q.fs.slice) == 0 { 62 | ret = pop 63 | break 64 | } 65 | q.ss.Push(pop) 66 | } 67 | for len(q.ss.slice) > 0 { 68 | pop, _ := q.ss.Pop() 69 | q.fs.Push(pop) 70 | } 71 | return 72 | } 73 | 74 | func (q *queueFromStack) String() string { 75 | return fmt.Sprintf("%#v", q.fs) 76 | } 77 | -------------------------------------------------------------------------------- /23_sort/main.go: -------------------------------------------------------------------------------- 1 | package _3_sort 2 | 3 | // BubbleSort n^2 4 | // 冒泡排序的大错觉: 是j 和 j+1 的对比,而不是i和j的比较 5 | func BubbleSort(nums []int) []int { 6 | for i := 0; i < len(nums); i++ { 7 | for j := 0; j < len(nums)-1; j++ { 8 | if nums[j] > nums[j+1] { 9 | nums[j+1], nums[j] = nums[j], nums[j+1] 10 | } 11 | } 12 | } 13 | return nums 14 | } 15 | 16 | // SelectSort 选择排序 n^2 17 | // SelectSort 是 min 和 j 比, min 和 i 换 18 | // 假设i是最小的那个数,然后向后比较,一旦发现比i小的数字,则用min记录,最终将min和i交换 19 | // j 只是用于记录sorted 和 unsorted 的界限 20 | func SelectSort(nums []int) []int { 21 | for i := 0; i < len(nums); i++ { 22 | var min int = i 23 | for j := i; j < len(nums); j++ { 24 | if nums[min] > nums[j] { 25 | min = j 26 | } 27 | } 28 | nums[i], nums[min] = nums[min], nums[i] 29 | } 30 | return nums 31 | } 32 | 33 | // Merge Sort n*log(n) 34 | // MergeSort = Merge将两个array合并 + MergeSort 35 | func MergeSort(nums []int) []int { 36 | if len(nums) == 1 { 37 | return nums 38 | } 39 | left := nums[:len(nums)/2] 40 | right := nums[len(nums)/2:] 41 | return merge(MergeSort(left), MergeSort(right)) 42 | } 43 | 44 | func merge(left, right []int) []int { 45 | var result []int 46 | var l, r = 0, 0 47 | for { 48 | if left[l] < right[r] { 49 | result = append(result, left[l]) 50 | l++ 51 | } else { 52 | result = append(result, right[r]) 53 | r++ 54 | } 55 | 56 | if l == len(left) { 57 | result = append(result, right[r:]...) 58 | return result 59 | } 60 | if r == len(right) { 61 | result = append(result, left[l:]...) 62 | return result 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /17_linked_list/main_test.go: -------------------------------------------------------------------------------- 1 | package linked_list 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | // 插入测试 9 | func TestLinkedList_InsertFirst(t *testing.T) { 10 | list := NewLinkedList() 11 | list.InsertFirst(1) 12 | fmt.Println(list, list.Size()) 13 | list.InsertFirst(2) 14 | fmt.Println(list, list.Size()) 15 | list.InsertFirst(3) 16 | fmt.Println(list, list.Size()) 17 | fmt.Println(list.GetFirst()) 18 | fmt.Println(list.GetLast()) 19 | list.Clear() 20 | fmt.Println(list) 21 | } 22 | 23 | // 插入尾测试 24 | func TestLinkedList_InsertLast(t *testing.T) { 25 | list := NewLinkedList() 26 | list.InsertLast(1) 27 | fmt.Println(list, list.Size()) 28 | list.InsertLast(2) 29 | fmt.Println(list, list.Size()) 30 | list.InsertLast(3) 31 | fmt.Println(list, list.Size()) 32 | fmt.Println(list.GetFirst()) 33 | fmt.Println(list.GetLast()) 34 | list.Clear() 35 | fmt.Println(list) 36 | } 37 | 38 | // 删除头测试 39 | func TestLinkedList_RemoveFirst(t *testing.T) { 40 | list := NewLinkedList() 41 | list.InsertFirst(1) 42 | fmt.Println(list, list.Size()) 43 | list.InsertFirst(2) 44 | fmt.Println(list, list.Size()) 45 | list.InsertFirst(3) 46 | fmt.Println(list, list.Size()) 47 | list.RemoveFirst() 48 | fmt.Println(list, list.Size()) 49 | list.RemoveFirst() 50 | fmt.Println(list, list.Size()) 51 | list.RemoveFirst() 52 | } 53 | 54 | // 删除尾测试 55 | func TestLinkedList_RemoveLast(t *testing.T) { 56 | list := NewLinkedList() 57 | fmt.Println(list, list.Size()) 58 | list.InsertFirst(1) 59 | fmt.Println(list, list.Size()) 60 | list.InsertFirst(2) 61 | fmt.Println(list, list.Size()) 62 | list.InsertFirst(3) 63 | fmt.Println(list, list.Size()) 64 | list.RemoveLast() 65 | fmt.Println(list, list.Size()) 66 | list.RemoveLast() 67 | fmt.Println(list, list.Size()) 68 | list.RemoveLast() 69 | fmt.Println(list, list.Size()) 70 | } 71 | 72 | // 获取第X个的测试 73 | func TestLinkedList_GetAt(t *testing.T) { 74 | list := NewLinkedList() 75 | list.InsertFirst(1) 76 | list.InsertFirst(2) 77 | list.InsertFirst(3) 78 | fmt.Println(list.GetAt(0)) 79 | fmt.Println(list.GetAt(1)) 80 | fmt.Println(list.GetAt(2)) 81 | fmt.Println(list, list.Size()) 82 | } 83 | 84 | // 删除第X个的测试 85 | func TestLinkedList_RemoveAt(t *testing.T) { 86 | list := NewLinkedList() 87 | list.InsertFirst(1) 88 | list.InsertFirst(2) 89 | list.InsertFirst(3) 90 | fmt.Println(list, list.Size()) 91 | list.RemoveAt(1) 92 | fmt.Println(list, list.Size()) 93 | } 94 | -------------------------------------------------------------------------------- /22_bst/main.go: -------------------------------------------------------------------------------- 1 | package _2_bst 2 | 3 | // 二分查找树 binary search tree 4 | // 二分查找树的典型特征《必记》: 5 | // 1. 只能有最多,两个节点(左,右节点) 6 | // 2. 左 < 父 < 右 7 | 8 | // 一个二分查找树,主要的方法就是两个: 9 | // Add 用于构建树 10 | // Search 用于查找某一个元素是否存在 11 | 12 | // 面试中:最最常见的一个关于二分查找的问题,如何验证一个二分树,是否满足二分查找树 13 | 14 | type BSTNode struct { 15 | Data int 16 | Left *BSTNode 17 | Right *BSTNode 18 | } 19 | 20 | func NewBSTNode(data int) *BSTNode { 21 | return &BSTNode{ 22 | Data: data, 23 | } 24 | } 25 | 26 | func (node *BSTNode) add(data int) { 27 | switch { 28 | case data < node.Data && node.Left != nil: 29 | node.Left.add(data) 30 | case node.Data < data && node.Right != nil: 31 | node.Right.add(data) 32 | case data < node.Data && node.Left == nil: 33 | node.Left = NewBSTNode(data) 34 | case node.Data < data && node.Right == nil: 35 | node.Right = NewBSTNode(data) 36 | } 37 | } 38 | 39 | func (node *BSTNode) search(data int) bool { 40 | switch { 41 | case node.Data == data: 42 | return true 43 | case data < node.Data && node.Left != nil: 44 | return node.Left.search(data) 45 | case node.Data < data && node.Right != nil: 46 | return node.Right.search(data) 47 | default: 48 | return false 49 | } 50 | } 51 | 52 | type BSTTree struct { 53 | Root *BSTNode 54 | } 55 | 56 | func NewBSTTree() *BSTTree { 57 | return &BSTTree{} 58 | } 59 | 60 | func (tree *BSTTree) Add(data int) { 61 | if tree.Root == nil { 62 | tree.Root = NewBSTNode(data) 63 | return 64 | } 65 | tree.Root.add(data) 66 | } 67 | 68 | func (tree *BSTTree) Search(data int) bool { 69 | if tree.Root == nil { 70 | return false 71 | } 72 | return tree.Root.search(data) 73 | } 74 | 75 | // 验证一个二分树是否满足BST 76 | // 牢记一点,并不是 左右子树都是二分树,父树就是二分树的,特例 [10,5,15,null,null,6,20] 77 | // 二分查找树的特性并不是 : 左节点 < 父 < 右节点,这是bstnode的特性 78 | // 二分查找树的特性是 : ** 左树的最大 < 父 < 右树的最小 且 左树,右树,也是二分查找树 ** 79 | // 所以问题就转化为了,求一颗树的最大和最小 80 | // 对应 leetCode 98 题,数据结构就采用 leetCode上的数据结构了 81 | 82 | // todo 优化: 目前我按照 大于左边最大,小于右边最小来计算,会导致会对 min, max 进行多次的重复计算,好处是思路,代码清晰 83 | // 优化思路是,** 左子树要小于的值 = 父节点要大于的值, 右子树要大于的值 = 父节点要小于的值 ** 重要 84 | // 即 isV(node *TreeNode, min int, minExit bool, max int, maxExit bool) 85 | // 然后 对于左右就要在多判断集中情况 86 | type TreeNode struct { 87 | Val int 88 | Left *TreeNode 89 | Right *TreeNode 90 | } 91 | 92 | func isValidBST(node *TreeNode) bool { 93 | if node == nil { 94 | return true 95 | } 96 | // 左 97 | var leftStatus bool 98 | switch { 99 | case node.Left != nil && node.Val <= min(node.Left): 100 | leftStatus = false 101 | case node.Left != nil && node.Val > min(node.Left): 102 | leftStatus = isValidBST(node.Left) 103 | default: 104 | leftStatus = true 105 | } 106 | // 右 107 | var rightStatus bool 108 | switch { 109 | case node.Right != nil && node.Val >= max(node.Right): 110 | rightStatus = false 111 | case node.Right != nil && node.Val < max(node.Right): 112 | rightStatus = isValidBST(node.Right) 113 | default: 114 | rightStatus = true 115 | } 116 | // 必须同时为真 117 | return leftStatus && rightStatus 118 | } 119 | 120 | // 最小 121 | func min(node *TreeNode) int { 122 | for node.Right != nil { 123 | node = node.Right 124 | } 125 | return node.Val 126 | } 127 | 128 | // 最大 129 | func max(node *TreeNode) int { 130 | for node.Left != nil { 131 | node = node.Left 132 | } 133 | return node.Val 134 | } 135 | 136 | // 之前的思维,太过于宏观,不够微观,不够一步一步来 137 | // 判断第一个节点的时候,不用去想,是否满足 大于左边整个子树的最大值,也不考虑右边,只是考虑自己 138 | // 把烦人的判断交给后面的节点 139 | // 比如它的左节点(以及左节点所有的子节点),就要满足不能超过上限,就是当前节点的值,而它的右边节点(以及所有的子节点),要满足一个下限,就是不能低于当前节点的值 140 | // 此时来描述一个二分查找树: 141 | // 《重要》 142 | // 我大于(右子节点),则我的所有孩子,不论左右,都会大于 143 | // 我小于(左子节点),则我的所有孩子,不论左右,都会小于 144 | // 《重要》 145 | func validBST(node *TreeNode, min *int, max *int) bool { 146 | switch { 147 | case node == nil: 148 | return true 149 | case min != nil && node.Val <= *min: 150 | return false 151 | case max != nil && node.Val >= *max: 152 | return false 153 | case node.Left != nil && !validBST(node.Left, min, &node.Val): 154 | return false 155 | case node.Right != nil && !validBST(node.Right, &node.Val, max): 156 | return false 157 | default: 158 | return true 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /17_linked_list/main.go: -------------------------------------------------------------------------------- 1 | package linked_list 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | // 最常在面试中出现的数据结构 9 | 10 | // 如何实现一个linked list 11 | type Node struct { 12 | Data interface{} 13 | Next *Node 14 | } 15 | 16 | func NewNode(data interface{}, nextNode *Node) *Node { 17 | return &Node{ 18 | Data: data, 19 | Next: nextNode, 20 | } 21 | } 22 | 23 | // 整理一下实现一个LinkedList,要考虑的各种特殊情况: 24 | // 1. 新增即换头 25 | // 2. 头很重要: 对head是否等于nil的判断,对于 删除,新增操作等 26 | // 3. 头尾一体的特殊情况: 在删除尾巴的时候,如果头尾一体,即只有一个节点,也要当作特殊情况处理 27 | // 3. size 方法,如果不是用遍历的方式,则对应所有的新增和删除都要添加对size的操作 28 | // 4. 带有index都要考虑到3种情况,头,尾,中间,并且遍历的时候,要找index-1的位置,这个位置是操作位置 29 | type LinkedList struct { 30 | head *Node 31 | size int 32 | } 33 | 34 | func NewLinkedList() *LinkedList { 35 | return &LinkedList{} 36 | } 37 | 38 | func (l *LinkedList) InsertFirst(data interface{}) { 39 | newNode := NewNode(data, nil) 40 | if l.head != nil { 41 | newNode.Next = l.head 42 | } 43 | l.head = newNode 44 | l.size += 1 45 | } 46 | 47 | // InsertLast 和size一样,有两种实现方式: 48 | // O(n) 的方式是,每次遍历到最后一个节点,然后进行新增 49 | // O(1) 的方法是,保存一个tail的标记,但是则需要在 Insert,Remove 等多个方法中维护这个标记,就会很复杂 50 | func (l *LinkedList) InsertLast(data interface{}) { 51 | newNode := NewNode(data, nil) 52 | if l.head == nil { 53 | l.head = newNode 54 | return 55 | } 56 | node := l.head 57 | for node.Next != nil { 58 | node = node.Next 59 | } 60 | node.Next = newNode 61 | 62 | l.size += 1 63 | } 64 | 65 | func (l *LinkedList) GetFirst() interface{} { 66 | // 记住要判断head是否为nil 67 | if l.head == nil { 68 | return nil 69 | } 70 | return l.head.Data 71 | } 72 | 73 | func (l *LinkedList) GetLast() interface{} { 74 | node := l.head 75 | if node == nil { 76 | return nil 77 | } 78 | for node.Next != nil { 79 | node = node.Next 80 | } 81 | return node.Data 82 | } 83 | 84 | func (l *LinkedList) Head() *Node { 85 | return l.head 86 | } 87 | 88 | func (l *LinkedList) Size() int { 89 | // 用遍历的一边的方式获取linked的大小 90 | //size := 0 91 | //var node *Node 92 | //node = l.head 93 | //for node != nil { 94 | // size += 1 95 | // node = node.Next 96 | //} 97 | return l.size 98 | } 99 | 100 | func (l *LinkedList) Clear() { 101 | node := l.head 102 | if node == nil { 103 | return 104 | } 105 | for node != nil { 106 | nextnode := node.Next 107 | node.Next = nil 108 | node = nextnode 109 | } 110 | // 将 head 设置为空(重要),同时要将 size 设置为 0 111 | l.head = nil 112 | l.size = 0 113 | } 114 | 115 | func (l *LinkedList) RemoveFirst() { 116 | if l.head == nil { 117 | return 118 | } 119 | 120 | oldhead := l.head 121 | l.head = oldhead.Next 122 | oldhead.Next = nil 123 | 124 | l.size -= 1 125 | } 126 | 127 | func (l *LinkedList) RemoveLast() { 128 | defer func() { 129 | l.size -= 1 130 | }() 131 | 132 | if l.head == nil { 133 | return 134 | } 135 | // 只有一个节点的情况 136 | if l.head.Next == nil { 137 | l.head = nil 138 | return 139 | } 140 | 141 | node := l.head 142 | // 重要,不能这么写,应为当只有一个node的时候,不存在倒数第二个node 143 | // 永远只找倒数第一,不找倒数第二 144 | for node.Next.Next != nil { 145 | node = node.Next 146 | } 147 | 148 | node.Next = nil 149 | } 150 | 151 | func (l *LinkedList) GetAt(index int) (data interface{}) { 152 | if l.size == 0 || index > l.size-1 || index < 0 { 153 | return nil 154 | } 155 | node := l.head 156 | count := 0 157 | for node.Next != nil { 158 | if count == index { 159 | break 160 | } 161 | node = node.Next 162 | count += 1 163 | } 164 | return node.Data 165 | } 166 | 167 | func (l *LinkedList) RemoveAt(index int) { 168 | if l.size == 0 || index > l.size-1 || index < 0 { 169 | return 170 | } 171 | // 2种情况 172 | // 1. 有一个节点 173 | // 2. 有多个节点 174 | 175 | defer func() { 176 | l.size -= 1 177 | }() 178 | 179 | // 只有一个节点 180 | if index == 0 && l.size == 1 { 181 | l.RemoveFirst() 182 | return 183 | } 184 | 185 | // 有多个节点 186 | // 1. 删除头 187 | if index == 0 { 188 | l.RemoveFirst() 189 | return 190 | } 191 | // 2. 删除尾 192 | if index == l.size-1 { 193 | l.RemoveLast() 194 | return 195 | } 196 | // 3. 删除其他,找到index之前的那个节点 197 | node := l.head 198 | count := 0 199 | for node.Next != nil { 200 | if count == index-1 { 201 | break 202 | } 203 | node = node.Next 204 | count += 1 205 | } 206 | removeedNode := node.Next 207 | node.Next = node.Next.Next 208 | removeedNode.Next = nil 209 | return 210 | } 211 | 212 | func (l *LinkedList) String() string { 213 | var result []string 214 | var node *Node 215 | node = l.head 216 | for node != nil { 217 | result = append(result, fmt.Sprintf("%#v", node.Data)) 218 | node = node.Next 219 | } 220 | return strings.Join(result, " -> ") 221 | } 222 | --------------------------------------------------------------------------------