Go 语言入门:LeetCode 常用数据结构
本文档旨在帮助新手快速掌握 Go 语言中常用的基础语法和数据结构。
Happy Coding!
基础语法
官方入门Go语言之旅
在深入数据结构之前,我们先快速了解一下 Go 的一些基础语法。
标准输出
Go 的 fmt 包提供了丰富的函数用于格式化和输出数据。fmt.Println 和 fmt.Printf 是最常用的两个。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| package main
import ( "fmt" )
func main() { a := 10
fmt.Println(a)
fmt.Println("Hello" + ", " + "World!")
s := "abc" fmt.Println(s, a)
fmt.Printf("%s %d\n", s, a) }
|
条件判断
Go 的 if-else 结构与其它语言类似,但条件不需要用括号括起来。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package main
import ( "fmt" )
func main() { a := 10
if a > 5 { fmt.Println("a > 5") } else if a == 5 { fmt.Println("a == 5") } else { fmt.Println("a < 5") } }
|
循环
Go 只有一个循环关键字 for,但它能实现多种循环方式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| package main
import ( "fmt" )
func main() { for i := 0; i < 5; i++ { fmt.Print(i, " ") } fmt.Println()
num := 100 for num > 0 { fmt.Print(num, " ") num /= 2 } fmt.Println() }
|
核心数据结构
掌握以下数据结构是刷 LeetCode 的基础。
动态数组(切片)
Go 的切片(Slice)是对底层数组的封装,提供了更强大、灵活的动态数组功能。
初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| package main
import ( "fmt" )
func main() { var nums []int
nums = make([]int, 7)
nums = []int{1, 3, 5}
nums = make([]int, 7) for i := range nums { nums[i] = 2 }
fmt.Println(nums)
var dp [][]bool dp = make([][]bool, 3) for i := 0; i < len(dp); i++ { row := make([]bool, 3) for j := range row { row[j] = true } dp[i] = row }
fmt.Println(dp) }
|
常用操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| package main
import ( "fmt" )
func main() { n := 10 nums := make([]int, n)
fmt.Println(len(nums) == 0)
fmt.Println(len(nums))
nums = append(nums, 20) fmt.Println(len(nums))
fmt.Println(nums[len(nums)-1])
nums = nums[:len(nums)-1] fmt.Println(len(nums))
nums[0] = 11 fmt.Println(nums[0])
nums = append(nums[:3], append([]int{99}, nums[3:]...)...)
nums = append(nums[:2], nums[3:]...)
nums[0], nums[1] = nums[1], nums[0]
for _, num := range nums { fmt.Print(num, " ") } fmt.Println() }
|
栈
Go 没有内置的栈结构,但可以用切片(Slice)轻松实现。栈遵循“后进先出”(LIFO)的原则。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| package main
import ( "fmt" )
func main() { var s []int
s = append(s, 10) s = append(s, 20) s = append(s, 30)
fmt.Println(len(s) == 0)
fmt.Println(len(s))
fmt.Println(s[len(s)-1])
s = s[:len(s)-1]
fmt.Println(s[len(s)-1]) }
|
队列
队列遵循“先进先出”(FIFO)的原则。Go 的标准库 container/list 提供了一个双向链表,可以高效地实现队列。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| package main
import ( "container/list" "fmt" )
func main() { q := list.New()
q.PushBack(10) q.PushBack(20) q.PushBack(30)
fmt.Println(q.Len() == 0)
fmt.Println(q.Len())
front := q.Front().Value.(int) fmt.Println(front)
q.Remove(q.Front())
newFront := q.Front().Value.(int) fmt.Println(newFront) }
|
哈希表(Map)
Go 内置了 map 类型来实现哈希表,用于存储键值对。
初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| package main
import ( "fmt" )
func main() { var hashmap map[int]string hashmap = make(map[int]string)
hashmap = map[int]string{ 1: "one", 2: "two", 3: "three", }
fmt.Println(hashmap) }
|
常用操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| package main
import ( "fmt" )
func main() { hashmap := make(map[int]string) hashmap[1] = "one" hashmap[2] = "two" hashmap[3] = "three"
fmt.Println(len(hashmap) == 0)
fmt.Println(len(hashmap))
if val, exists := hashmap[2]; exists { fmt.Println("Key 2 ->", val) } else { fmt.Println("Key 2 not found.") }
fmt.Println(hashmap[4])
hashmap[4] = "four"
fmt.Println(hashmap[4])
delete(hashmap, 3)
if val, exists := hashmap[3]; exists { fmt.Println("Key 3 ->", val) } else { fmt.Println("Key 3 not found.") }
for key, value := range hashmap { fmt.Printf("%d -> %s\n", key, value) } }
|
哈希集合 (Set)
Go 没有内置的集合类型,但可以用 map[T]struct{} 巧妙地实现。struct{} 是一个空结构体,不占用任何内存空间,非常适合用作集合的值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| package main
import ( "fmt" )
func main() { hashset := map[int]struct{}{ 1: {}, 2: {}, 3: {}, 4: {}, }
fmt.Println(len(hashset) == 0)
fmt.Println(len(hashset))
if _, exists := hashset[3]; exists { fmt.Println("Element 3 found.") } else { fmt.Println("Element 3 not found.") }
hashset[5] = struct{}{}
delete(hashset, 2) if _, exists := hashset[2]; exists { fmt.Println("Element 2 found.") } else { fmt.Println("Element 2 not found.") }
for element := range hashset { fmt.Println(element) } }
|
双向链表
Go 的 container/list 包提供了一个功能完备的双向链表实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| package main
import ( "container/list" "fmt" )
func main() { lst := list.New() lst.PushBack(1) lst.PushBack(2) lst.PushBack(3) lst.PushBack(4) lst.PushBack(5)
fmt.Println(lst.Len() == 0)
fmt.Println(lst.Len())
lst.PushFront(0) lst.PushBack(6)
front := lst.Front().Value.(int) back := lst.Back().Value.(int) fmt.Println(front, back)
lst.Remove(lst.Front()) lst.Remove(lst.Back())
third := lst.Front().Next().Next() lst.InsertBefore(99, third)
second := lst.Front().Next() lst.Remove(second)
for e := lst.Front(); e != nil; e = e.Next() { fmt.Print(e.Value.(int), " ") } fmt.Println() }
|