切片
var a = []int{1, 2, 3, 4}
a = append(a, 5) // 在后面添加
b := a[:len(a)-1] // 删除最后一个,并把最后一个返回给b
c := append(a[0:2], a[3:]...) // 删除中间元素
链表
type Node struct {
Data int
Next *Node
}
type List struct {
headNode *Node
}
// IsEmpty 判断链表是否为空
func (this *List) IsEmpty() bool {
if this.headNode == nil {
return true
} else {
return false
}
}
// Length 获得链表长度
func (this *List) Length() int {
cur := this.headNode
count := 0
for cur != nil {
count++
cur = cur.Next
}
return count
}
// Add 在链表头部添加元素
func (this *List) Add(data int) {
node := &Node{Data: data}
node.Next = this.headNode
this.headNode = node
return
}
// Append 在链表尾部添加元素
func (this *List) Append(data int) {
node := &Node{Data: data}
if this.IsEmpty() {
this.headNode = node
} else {
cur := this.headNode
for cur.Next != nil {
cur = cur.Next
}
cur.Next = node
}
}
// Insert 在某个位置插入
func (this *List) Insert(index int, data int) {
if index < 0 {
this.Add(data)
} else if index > this.Length() {
this.Append(data)
} else {
count := 0
cur := this.headNode
for count < (index - 1) {
cur = cur.Next
count++
}
node := &Node{Data: data}
node.Next = cur.Next
cur.Next = node
}
}
栈
var a = []int{1,2}
// 入栈
a = append(a,3)
// 出栈
b := a[len(a)-1]
a = a[:len(a)-1]
队列
var queue = []int{1,2}
// 入队
queue = append(0,queue)
// 出队
r := queue[len(queue)-1]
queue = queue[len(queue)-1]
双端队列
var queue = []int{1,2}
// 左入队
queue = append(0,queue)
// 右入队
queue = append(queue,3)
// 右出队
r := queue[len(queue)-1]
queue = queue[:len(queue)-1]
// 左出队
r := queue[0]
queue = queue[1:]
哈希表和映射
var dic = map[string]int{'a': 12, 'b': 23}
dic['c'] = 34 //添加
if value,ok := dic['a'];ok==true{
data = value //获得,如果不存在则不赋值
}
delete(dic, 'a') //删除
集合(用map实现)
hashSet := make(map[string]struct{}) //初始化
data := []string{"Hello", "World", "213", "3213", "213", "World"}
for _,v := range data{
hashSet[v] = struct{}{} //添加
}
for k,_ := range hashSet{
fmt.Println(k) //打印
}
delete(hashSet, "Hello") //删除
单调栈
此类问题可以在左右两边加入哨兵,比如柱状图中最大的矩形这道题。
func largestRectangleArea() int {
heights := []int{2,1,5,6,2,3}
// 单调递增栈
ans := 0
heights = append([]int{0},heights...) // 加入左哨兵
heights = append(heights,[]int{0}...) // 加入右哨兵
stack := []int{0} // 栈,左哨兵入栈
for i:=1;i<len(heights);i++{
for heights[i] < heights[stack[len(stack)-1]]{
// 出栈
popi := stack[len(stack)-1]
stack = stack[:len(stack)-1]
// 计算popi的值
tmp := heights[popi]*(i-stack[len(stack)-1]-1)
if tmp > ans{
ans = tmp
}
}
// 入栈
stack = append(stack,i)
}
return ans
}
单调队列
以滑动窗口最大值为例。
// 单调递减双端队列
// nums = [1,3,-1,-3,5,3,6,7]
func maxSlidingWindow(nums []int, k int) []int {
// 特殊情况
if k == 1{
return nums
}
queue := []int{0} // 第一个元素入队
// k窗口全部右入队
for i := 1;i<k;i++{
for nums[i]>nums[queue[len(queue)-1]]{
// 右出队
queue = queue[:len(queue)-1]
if len(queue) ==0{
break
}
}
queue = append(queue,i) // 右入队
}
ans := []int{nums[queue[0]]}
for i := k;i<len(nums);i++{
if i-k == queue[0]{
// 左出队
queue = queue[1:]
}
for nums[i]>nums[queue[len(queue)-1]]{
// 右出队
queue = queue[:len(queue)-1]
if len(queue) ==0{
break
}
}
queue = append(queue,i) // 右入队
ans = append(ans,nums[queue[0]]) // 保存结果
}
return ans
}
二叉树
type TreeNode struct{
Val int
Left *TreeNode
Right *TreeNode
}
中序遍历
func inorderTraversal(root *TreeNode) []int {
if root != nil{
r := inorderTraversal(root.Left)
r = append(r,root.Val)
r = append(r,inorderTraversal(root.Right)...)
return r
}else{
return []int{}
}
}
递归
func recursion(level, param1, param2, ... int){
//递归终止条件
if level > MAX_LEVEL{
result = append(result, ) //result添加和处理
return
}
//当前层的逻辑处理部分
...
//进入下一层
recursion(level+1, param1, param2, ...)
//返回当前层状态
return
}
分治
func divide_conquer(problem , param1, param2, ...,int) int {
//分治终止条件
if problem == nil:
return value
//当前层的逻辑处理部分
data := prepare_data(problem)
subs := split_problem(problem, data)
//进入下一层计算子问题
sub1 := divide_conquer(subs[0], param1, param2, ...)
sub2 := divide_conquer(subs[1], param1, param2, ...)
sub3 := divide_conquer(subs[2], param1, param2, ...)
...
//最终结果计算
result := process_result(sub1, sub2, sub3, ...)
return result
}
回溯
func backtracking(item int) bool {
#回溯终止条件
if item == len(LIST):
return true
#当前层的逻辑处理部分
index := prepare_index(item)
#回溯
for f in OUTSIDE_LIST(index):
#改变result
change_result(result)
#进入下一层
if recall(item+1):
return True
#回复刚刚改过的result
reply_result(result)
#返回当前层状态
return false
}
深度优先搜索
def dfs(node *TreeNode, visited map[*TreeNode]int):
if _,ok:=visited[node];ok{ //终止条件
//这个节点已经拜访了
return
}
//记录拜访节点
visited[node] = 0
//当前层的逻辑处理部分
...
for _,next_node := range node.Children{
if _,ok:=visited[next_node];!ok{
dfs(next_node, visited)
}
}
广度优先搜索
//第一种写法
func bfs(root *TreeNode){
queue := []*TreeNode{}
queue = append(queue,root)
for len(queue) != 0{
node := queue[0]
queue = queue[1:]
process(node)
nodes := node.Children
queue = append(queue,nodes...)
}
//其他工作
}
//第二种写法
func bfs(root *TreeNode){
queue := []*TreeNode{}
queue = append(queue,root)
for len(queue) != 0{
child := []*TreeNode{}
for _,node :=range queue{
process(node)
nodes := node.Children
child = append(child,nodes...)
}
queue = child
}
//其他工作
}
双向广度优先搜索
func DBFS(beginnode string, endnode string){
beginqueue := []string{beginnode}
endqueue := []string{endnode}
while len(beginqueue)!=0 and len(endqueue)!=0{
if len(beginqueue) > len(endqueue){
beginqueue, endqueue = endqueue, beginqueue
}
child := []string{}
for _,node := range beginqueue{
visited[node] = 0
process(node)
nodes := generate_related_nodes(node)
if in(nodes,endqueue){
return
}
child := append(child,nodes...)
}
beginqueue = child
}
//其他工作
}
二分查找
left, right := 0, len(array)-1
for left <= right{
mid := (left+right)/2
if array[mid] == target{
break or return result
}else if array[mid] < target{
left = mid + 1
}else{
right = mid - 1
}
}
动态规划(不同路径ii)
func dp(i int,j int,m int,n int,opt *[][]int,obstacleGrid *[][]int)int{
if i == m && j == n{
if (*obstacleGrid)[i][j] == 1{
return 0
}
return 1
}
if (*opt)[i][j] == 0{
if (*obstacleGrid)[i][j] == 1{
(*opt)[i][j] = 0
}else{
if i+1 <= m && j+1 <= n{
(*opt)[i][j] = dp(i+1,j,m,n,opt,obstacleGrid)+dp(i,j+1,m,n,opt,obstacleGrid)
} else if i+1 <= m && j+1 > n{
(*opt)[i][j] = dp(i+1,j,m,n,opt,obstacleGrid)
}else if i+1 > m && j+1 <= n{
(*opt)[i][j] = dp(i,j+1,m,n,opt,obstacleGrid)
}
}
}
return (*opt)[i][j]
}
动态规划(最长公共子序列)
dp := [][]int{}
m := len(text1)
n := len(text2)
for i := 0;i<m+1;i++{
tmp := []int{}
for j := 0;j<n+1;j++{
tmp = append(tmp,0)
}
dp = append(dp,tmp)
}
for i := 1;i<m+1;i++{
for j := 1;j<n+1;j++{
if text1[i-1] == text2[j-1]{
dp[i][j] = dp[i-1][j-1] +1
}else{
dp[i][j] = max(dp[i-1][j],dp[i][j-1])
}
}
}
return dp[m][n]
动态规划(一维状态转移,最大子数组和)
max := 0
for i := 1;i<len(nums);i++{
if nums[i]+nums[i-1] > nums[i]{
nums[i] = nums[i]+nums[i-1]
}
if nums[i] > max{
max = nums[i]
}
}
return max
动态规划(二维状态转移,股票买卖ii)
dp := [][]int{}
for i := 0;i<len(prices);i++{
dp = append(dp,[]int{0,0})
}
for i := 0;i<len(prices);i++{
if i == 0{
dp[i][0] = -(prices[i])
dp[i][1] = 0
}else{
dp[i][0] = max(dp[i-1][0],dp[i-1][1]-prices[i])
dp[i][1] = max(dp[i-1][1],dp[i-1][0]+prices[i])
}
}
return dp[len(dp)-1][1]
动态规划(三维状态转移,股票买卖iii)
dp := [][][]int{}
for i:=0;i<len(prices);i++{
tmp := [][]int{}
for j := 0;j<3;j++{
tmp = append(tmp,[]int{0,0})
}
dp = append(dp,tmp)
}
for i := 0;i<len(prices);i++{
for j := 1;j<3;j++{
if i == 0{
dp[i][j][0],dp[i][j][1] = 0,-prices[i]
}else{
dp[i][j][0] = max(dp[i-1][j][0],dp[i-1][j][1]+prices[i])
dp[i][j][1] = max(dp[i-1][j][1],dp[i-1][j-1][0]-prices[i])
}
}
}
return dp[len(prices)-1][2][0]
动态规划(编辑距离)
func minDistance(word1 string, word2 string) int {
// init
dp := make([][]int,len(word1)+1)
for i := 0;i<len(word1)+1;i++{
dp[i] = make([]int,len(word2)+1)
}
for i := 0;i<len(word1)+1;i++{
for j:=0;j<len(word2)+1;j++{
if i == 0 && j == 0{
dp[i][j] = 0
continue
}
if i == 0 && j != 0{
dp[i][j] = dp[i][j-1] + 1
continue
}
if i != 0 && j == 0{
dp[i][j] = dp[i-1][j] + 1
continue
}
if word1[i-1] == word2[j-1]{
dp[i][j] = dp[i-1][j-1]
}else{
dp[i][j] = min(dp[i-1][j-1]+1,dp[i][j-1]+1,dp[i-1][j]+1)
}
}
}
return dp[len(word1)][len(word2)]
}
Tire树(字典树,前缀树)
type Trie struct {
lookup map[rune]interface{}
endOfWord rune
}
// Constructor 初始化
func Constructor() Trie {
trie := Trie{}
trie.lookup = make(map[rune]interface{})
trie.endOfWord = rune('#')
return trie
}
// Insert 插入
func (this *Trie) Insert(word string) {
tree := this.lookup
for _,v := range word{
if _,ok := tree[v];!ok{
tree[v] = make(map[rune]interface{})
}
tree = tree[v].(map[rune]interface{})
}
tree[this.endOfWord] = make(map[rune]interface{})
}
// Search 搜索
func (this *Trie) Search(word string) bool {
tree := this.lookup
for _,v := range word{
if _,ok := tree[v];ok{
tree = tree[v].(map[rune]interface{})
}else{
return false
}
}
if _,ok := tree[this.endOfWord];ok{
return true
}
return false
}
// StartsWith 子集
func (this *Trie) StartsWith(prefix string) bool {
tree := this.lookup
for _,v := range prefix{
if _,ok := tree[v];ok{
tree = tree[v].(map[rune]interface{})
}else{
return false
}
}
return true
}
/**
* Your Trie object will be instantiated and called as such:
* obj := Constructor();
* obj.Insert(word);
* param_2 := obj.Search(word);
* param_3 := obj.StartsWith(prefix);
*/
位运算
// 判断奇偶
(x&1)==1 //奇
(x&1)==0 //偶
x = x>>1 //x=x/2,运算更快
X=X&(X-1) //清零最低位的1
X&(-X) //得到最低位的1
(x>>n)&1 //获取x的第n位的值(0或1)
x&(1<<(n-1)) //获取x第n位的幂值
快速排序
func quickSort(array []int, begin int, end int) {
if begin >= end {
return
}
counter := begin
for i := begin; i < end; i++ {
if array[i] < array[end] {
array[counter], array[i] = array[i], array[counter]
counter++
}
}
array[counter], array[end] = array[end], array[counter]
quickSort(array, begin, counter-1)
quickSort(array, counter+1, end)
}
归并排序
func mergeSort(array []int, begin int, end int) {
if begin >= end {
return
}
mid := (begin + end) / 2
mergeSort(array, begin, mid)
mergeSort(array, mid+1, end)
tmp := []int{}
i, j := begin, mid+1
for i <= mid && j <= end {
if array[i] <= array[j] {
tmp = append(tmp, array[i])
i++
} else {
tmp = append(tmp, array[j])
j++
}
}
for i <= mid {
tmp = append(tmp, array[i])
i++
}
for j <= end {
tmp = append(tmp, array[j])
j++
}
for k := begin; k <= end; k++ {
array[k] = tmp[k-begin]
}
}
堆排序
type IntHeap []int
func (h IntHeap) Len() int { return len(h) }
func (h IntHeap) Less(i, j int) bool { return h[i] < h[j] }
func (h IntHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *IntHeap) Push(x interface{}) {
*h = append(*h, x.(int))
}
func (h *IntHeap) Pop() interface{} {
x := (*h)[len(*h)-1]
*h = (*h)[0 : len(*h)-1]
return x
}
func heapSort(array []int) {
h := &IntHeap{}
heap.Init(h)
for i := 0; i < len(array); i++ {
heap.Push(h, array[i])
}
for i := 0; i < len(array); i++ {
array[i] = heap.Pop(h).(int)
}
}