k8s节点下线流程梳理
滑动窗口
3. 无重复字符的最长子串
func lengthOfLongestSubstring(s string) (ans int) {
ss := [128]bool{}
for i, j := 0, 0; j < len(s); j++ {
for ss[s[j]] {
ss[s[i]] = false
i++
}
ss[s[j]] = true
ans = max(ans, j-i+1)
}
return
}
438. 找到字符串中所有字母异位词
func findAnagrams(s string, p string) (ans []int) {
m, n := len(s), len(p)
if m < n {
return
}
cnt1 := [26]int{}
cnt2 := [26]int{}
for _, c := range p {
cnt1[c-'a']++
}
for _, c := range s[:n-1] {
cnt2[c-'a']++
}
for i := n - 1; i < m; i++ {
cnt2[s[i]-'a']++
if cnt1 == cnt2 {
ans = append(ans, i-n+1)
}
cnt2[s[i-n+1]-'a']--
}
return
}
子串
239. 滑动窗口最大值
func maxSlidingWindow(nums []int, k int) (ans []int) {
q := []int{}
for i, v := range nums {
for len(q) > 0 && i-k+1 > q[0] {
q = q[1:]
}
for len(q) > 0 && nums[q[len(q)-1]] <= v {
q = q[:len(q)-1]
}
q = append(q, i)
if i >= k-1 {
ans = append(ans, nums[q[0]])
}
}
return
}
76. 最小覆盖子串
func minWindow(s string, t string) string {
need := [128]int{}
window := [128]int{}
for _, c := range t {
need[c]++
}
cnt, j, k, mi := 0, 0, -1, 1<<30
for i, c := range s {
window[c]++
if need[c] >= window[c] {
cnt++
}
for cnt == len(t) {
if i-j+1 < mi {
mi = i - j + 1
k = j
}
if need[s[j]] >= window[s[j]] {
cnt--
}
window[s[j]]--
j++
}
}
if k < 0 {
return ""
}
return s[k : k+mi]
}
矩阵
54. 螺旋矩阵
func spiralOrder(matrix [][]int) []int {
var ans []int
m, n := len(matrix), len(matrix[0])
dirs := [4][2]int{{0, 1}, {1, 0}, {0, -1}, {-1, 0}}
i, j, k := 0, 0, 0
for h := 0; h < m*n; h++ {
ans = append(ans, matrix[i][j])
matrix[i][j] = 1<<30
x, y := i+dirs[k][0], j+dirs[k][1]
if x < 0 || x >= m || y < 0 || y >= n || matrix[x][y] == 1<<30 {
k = (k + 1) % 4
}
i, j = i+dirs[k][0], j+dirs[k][1]
}
return ans
}
变形 蛇形打印上三角
MiniMax
package main
import (
"fmt"
)
// printSnakeUpperTriangular 打印上三角的蛇形排序
func printSnakeUpperTriangular(matrix [][]int) {
n := len(matrix) // 矩阵的维度
var layers [][]int // 存储每层的元素
// 收集每层的元素
for i := 0; i < n; i++ {
var layer []int
for j := 0; j <= i; j++ {
layer = append(layer, matrix[i-j][j])
}
layers = append(layers, layer)
}
// 根据层的奇偶性打印元素
for i, layer := range layers {
if i%2 == 1 {
for _, val := range layer {
fmt.Printf("%d ", val)
}
} else {
for j := len(layer) - 1; j >= 0; j-- {
fmt.Printf("%d ", layer[j])
}
}
}
fmt.Println()
}
func main() {
matrix := [][]int{
{1, 3, 4, 10},
{2, 5, 9, 0},
{6, 8, 0, 0},
{7, 0, 0, 0},
}
printSnakeUpperTriangular(matrix)
}
链表
92. 反转链表 II
func reverseBetween(head *ListNode, left int, right int) *ListNode {
if head.Next == nil || left == right {
return head
}
dummy := &ListNode{0, head}
pre := dummy
for i := 0; i < left-1; i++ {
pre = pre.Next
}
p, q := pre, pre.Next
cur := q
for i := 0; i < right-left+1; i++ {
t := cur.Next
cur.Next = pre
pre = cur
cur = t
}
p.Next = pre
q.Next = cur
return dummy.Next
}
25. K 个一组翻转链表
func reverseKGroup(head *ListNode, k int) *ListNode {
start, end := head, head
for i := 0; i < k; i++ {
if end == nil {
return head
}
end = end.Next
}
res := reverse(start, end)
start.Next = reverseKGroup(end, k)
return res
}
func reverse(start, end *ListNode) *ListNode {
var pre *ListNode = nil
for start != end {
tmp := start.Next
start.Next, pre = pre, start
start = tmp
}
return pre
}
146. LRU 缓存
type node struct {
key, val int
prev, next *node
}
type LRUCache struct {
capacity int
head, tail *node
cache map[int]*node
}
func Constructor(capacity int) LRUCache {
head := new(node)
tail := new(node)
head.next = tail
tail.prev = head
return LRUCache{
capacity: capacity,
cache: make(map[int]*node, capacity),
head: head,
tail: tail,
}
}
func (this *LRUCache) Get(key int) int {
n, ok := this.cache[key]
if !ok {
return -1
}
this.moveToFront(n)
return n.val
}
func (this *LRUCache) Put(key int, value int) {
n,ok:=this.cache[key]
if ok{
n.val = value
this.moveToFront(n)
return
}
if len(this.cache) == this.capacity {
back := this.tail.prev
this.remove(back)
delete(this.cache,back.key)
}
n = &node{
key: key,
val:value,
}
this.pushFront(n)
this.cache[key]=n
}
func (this *LRUCache) remove(n *node) {
n.prev.next = n.next
n.next.prev = n.prev
n.prev = nil
n.next = nil
}
func (this *LRUCache) moveToFront(n *node){
this.remove(n)
this.pushFront(n)
}
func (this *LRUCache) pushFront(n *node){
t:=this.head.next
n.prev = this.head
n.next = t
this.head.next=n
t.prev=n
}
树
94. 二叉树的中序遍历
func inorderTraversal(root *TreeNode) []int {
var ans []int
stk := []*TreeNode{}
if root != nil {
stk = append(stk, root)
}
for len(stk) > 0 {
node := stk[len(stk)-1]
if node != nil {
stk = stk[:len(stk)-1]
if node.Right != nil {
stk = append(stk, node.Right)
}
stk = append(stk, node)
stk = append(stk, nil)
if node.Left != nil {
stk = append(stk, node.Left)
}
} else {
stk = stk[:len(stk)-1]
node = stk[len(stk)-1]
stk = stk[:len(stk)-1]
ans = append(ans, node.Val)
}
}
return ans
}
层序遍历
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
func zigzagLevelOrder(root *TreeNode) [][]int {
var ans [][]int
if root == nil {
return ans
}
q := []*TreeNode{root}
left := true
for len(q) > 0 {
t := []int{}
for n := len(q); n > 0; n-- {
node := q[0]
q = q[1:]
t = append(t, node.Val)
if node.Left != nil {
q = append(q, node.Left)
}
if node.Right != nil {
q = append(q, node.Right)
}
}
if !left {
reverseSlice(t)
}
left = !left
ans = append(ans, t)
}
return ans
}
func reverseSlice(s []int) {
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
s[i], s[j] = s[j], s[i]
}
}
236. 二叉树的最近公共祖先
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
if root == nil || root == p || root == q {
return root
}
left := lowestCommonAncestor(root.Left, p, q)
right := lowestCommonAncestor(root.Right, p, q)
if left != nil && right != nil {
return root
}
if left == nil {
return right
}
return left
}
124. 二叉树中的最大路径和
func maxPathSum(root *TreeNode) int {
ans := -1 << 30
var dfs func(*TreeNode) int
dfs = func(root *TreeNode) int {
if root == nil {
return 0
}
left := max(0, dfs(root.Left))
right := max(0, dfs(root.Right))
ans = max(ans, left+right+root.Val)
return max(left, right) + root.Val
}
dfs(root)
return ans
}
排序
快排
// 普通快排,左右指针普通版
// 每次递归,确定一个pivot的位置
// 基准元素必须为最左边或最右边,和基准元素比较时,必须为>=或<=,每次循环必须基准元素另一侧的指针先动。
func quickSort(arr []int, l, r int) {
if l <= r {
pivot := arr[l]
i, j := l, r
for i < j {
for i < j && arr[j] >= pivot { // 此处因为是>=,所以必须基准元素对侧先动,不然如果基准元素是最小值(在此升序列条件下),基准侧先动,必然乱序。
j--
}
for i < j && arr[i] <= pivot {
i++
}
arr[i], arr[j] = arr[j], arr[i]
}
arr[l], arr[i] = arr[i], arr[l] // 交换基准元素和中间位置,此时i=j
quickSort(arr, l, i-1)
quickSort(arr, i+1, r)
}
}
// 左左指针版
// 每次递归,确定一个pivot的位置
// 若从左边开始,则基准元素必须为最右端元素
func quickSort(nums []int, l, r int) {
if l >= r {
return
}
i, j, x := l-1, r+1, nums[l]
for i < j {
for i++; nums[i] < x; i++ {
}
for j--; nums[j] > x; j-- {
}
if i < j {
nums[i], nums[j] = nums[j], nums[i]
}
}
quickSort(nums, l, j)
quickSort(nums, j+1, r)
}
215. 数组中的第K个最大元素
- 快速选择排序
func findKthLargest(nums []int, k int) int {
k = len(nums) - k
return quickSelect(nums, 0, len(nums)-1, k)
}
func quickSelect(nums []int, l, r, k int) int {
if l>=r {
return nums[l]
}
i,j,partition:=l-1,r+1,nums[l]
for i<j {
for i++;nums[i]<partition;i++{}
for j--;nums[j]>partition;j--{}
if i<j {
nums[i],nums[j]=nums[j],nums[i]
}
}
if j<k {
return quickSelect(nums,j+1,r,k)
}
return quickSelect(nums,l,j,k)
}
- 优先队列
type hp struct {
sort.IntSlice
}
func (h hp) Less(i, j int) bool { return h.IntSlice[i] < h.IntSlice[j] }
func (h *hp) Push(v any) { h.IntSlice = append(h.IntSlice, v.(int)) }
func (h *hp) Pop() any {
a := h.IntSlice
v := a[len(a)-1]
h.IntSlice = a[:len(a)-1]
return v
}
func findKthLargest(nums []int, k int) int {
minHeap := hp{}
for _, x := range nums {
heap.Push(&minHeap, x)
if minHeap.Len()>k{
heap.Pop(&minHeap)
}
}
return minHeap.IntSlice[0]
}
归并排序
func mergeSort(nums []int, l, r int) {
if l >= r {
return
}
mid := (l + r) >> 1
mergeSort(nums, l, mid)
mergeSort(nums, mid+1, r)
k, i, j := 0, l, mid+1
tmp := make([]int, r-l+1)
for i <= mid && j <= r {
if nums[i] < nums[j] {
tmp[k] = nums[i]
k, i = k+1, i+1
} else {
tmp[k] = nums[j]
k, j = k+1, j+1
}
}
for i <= mid {
tmp[k] = nums[i]
k, i = k+1, i+1
}
for j <= r {
tmp[k] = nums[j]
k, j = k+1, j+1
}
for i, j := l, 0; i <= r; i, j = i+1, j+1 {
nums[i] = tmp[j]
}
}
堆
type hp struct {
sort.IntSlice
}
func (h hp) Less(i, j int) bool { return h.IntSlice[i] < h.IntSlice[j] }
func (h *hp) Push(v any) { h.IntSlice = append(h.IntSlice, v.(int)) }
func (h *hp) Pop() any {
a := h.IntSlice
v := a[len(a)-1]
h.IntSlice = a[:len(a)-1]
return v
}
var _ heap.Interface = (*hp)(nil)
package main
import (
"container/heap"
"fmt"
)
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{} {
old := *h
n := len(old)
x := old[n-1]
*h = old[0 : n-1]
return x
}
func main() {
h := &IntHeap{2, 3, 1, 5}
heap.Init(h)
heap.Push(h, 4)
fmt.Printf("minimum: %d\n", (*h)[0])
for h.Len() > 0 {
fmt.Printf("%d ", heap.Pop(h).(int))
}
}
手写堆
package main
import "fmt"
type Heap struct {
data []int
}
func (h *Heap) down(i int) {
l, r, n := 2*i+1, 2*i+2, len(h.data)
t := i
if l < n && h.data[l] < h.data[i] {
t = l
}
if r < n && h.data[r] < h.data[i] {
t = r
}
if t != i {
h.data[i], h.data[t] = h.data[t], h.data[i]
h.down(t)
}
}
func (h *Heap) up(i int) {
for {
p := (i - 1) >> 1
if p < 0 || h.data[i] >= h.data[p] {
break
}
h.data[i], h.data[p] = h.data[p], h.data[i]
i = p
}
}
func (h *Heap) Push(i int) {
h.data = append(h.data, i)
h.up(len(h.data) - 1)
}
func (h *Heap) Pop() {
n := len(h.data)
h.data[0], h.data[n-1] = h.data[n-1], h.data[0]
h.data = h.data[:n-1]
h.down(0)
}
func main() {
nums := []int{10, 2, 4, 3, 6}
hp := &Heap{}
for _, v := range nums {
hp.Push(v)
}
for len(hp.data) > 0 {
fmt.Println(hp.data[0])
hp.Pop()
}
}
二分查找
l := sort.SearchInts(nums, target)
- 查找最左边值 / 最右边值
func leftBound(nums []int, target int) int {
l, r := 0, len(nums)-1
for l <= r {
mid := (l + r) >> 1
if nums[mid] == target {
r = mid - 1
} else if nums[mid] < target {
l = mid + 1
} else if nums[mid] > target {
r = mid - 1
}
}
return l
}
func rightBound(nums []int, target int) int {
l, r := 0, len(nums)-1
for l <= r {
mid := (l + r) >> 1
if nums[mid] == target {
l = mid + 1
} else if nums[mid] < target {
l = mid + 1
} else if nums[mid] > target {
r = mid - 1
}
}
return r
}
34. 在排序数组中查找元素的第一个和最后一个位置
func searchRange(nums []int, target int) []int {
l := sort.SearchInts(nums, target)
r := sort.SearchInts(nums, target+1)
if l == r {
return []int{-1, -1}
}
return []int{l, r - 1}
}
回溯
46. 全排列
func premute(nums []int) (ans [][]int) {
n := len(nums)
vis := make([]bool, n)
t := make([]int, n)
var dfs func(int)
dfs = func(i int) {
if i == n {
ans = append(ans, slices.Clone(t))
return
}
for j, v := range nums {
if !vis[j] {
vis[j] = true
t[i] = v
dfs(i + 1)
vis[j] = false
}
}
}
dfs(0)
return
}
78. 子集
func subsets(nums []int) [][]int {
var ans [][]int
t := []int{}
var dfs func(int)
dfs = func(i int) {
if i == len(nums) {
ans = append(ans, slices.Clone(t))
return
}
dfs(i + 1)
t = append(t, nums[i])
dfs(i + 1)
t = t[:len(t)-1]
}
dfs(0)
return ans
}
77. 组合
func combine(n int, k int) (ans [][]int) {
t := []int{}
var dfs func(int)
dfs = func(i int) {
if len(t) == k {
ans = append(ans, slices.Clone(t))
return
}
if i > n {
return
}
t = append(t, i)
dfs(i + 1)
t = t[:len(t)-1]
dfs(i + 1)
}
dfs(1)
return
}
51. N 皇后
func solveNQueens(n int) (ans [][]string) {
col := make([]int, n)
dg := make([]int, n<<1)
udg := make([]int, n<<1)
t := make([][]byte, n)
for i := range t {
t[i] = make([]byte, n)
for j := range t[i] {
t[i][j] = '.'
}
}
var dfs func(int)
dfs = func(i int) {
if i == n {
tmp := make([]string, n)
for i := range tmp {
tmp[i] = string(t[i])
}
ans = append(ans, tmp)
return
}
for j := 0; j < n; j++ {
if col[j]+dg[i+j]+udg[n-i+j] == 0 {
col[j], dg[i+j], udg[n-i+j] = 1, 1, 1
t[i][j] = 'Q'
dfs(i + 1)
t[i][j] = '.'
col[j], dg[i+j], udg[n-i+j] = 0, 0, 0
}
}
}
dfs(0)
return
}
动态规划
0-1背包问题
func knapsackDP(wgt, val []int, cap int) int {
n := len(wgt)
dp := make([]int, cap+1)
for i := 0; i < n; i++ {
for j := cap; j >= 1; j-- {
if wgt[i] <= j {
dp[j] = int(math.Max(float64(dp[j]), float64(dp[j-wgt[i]]+val[i])))
}
}
}
return dp[cap]
}
完全背包
func unboundedKnapsackDPComp(wgt, val []int, cap int) int {
n := len(wgt)
dp := make([]int, cap+1)
for i := 0; i < n; i++ {
for j := 1; j <= cap; j++ {
if wgt[i] <= j {
// 不选和选物品 i 这两种方案的较大值
dp[j] = int(math.Max(float64(dp[j]), float64(dp[j-wgt[i]]+val[i])))
}
}
}
return dp[cap]
}
322. 零钱兑换
func coinChange(coins []int, amount int) int {
m, n := len(coins), amount
f := make([][]int, m+1)
const inf = 1 << 30
for i := range f {
f[i] = make([]int, n+1)
for j := range f[i] {
f[i][j] = inf
}
}
f[0][0] = 0
for i := 1; i <= m; i++ {
for j := 0; j <= n; j++ {
f[i][j] = f[i-1][j]
if j >= coins[i-1] {
f[i][j] = min(f[i][j], f[i][j-coins[i-1]]+1)
}
}
}
if f[m][n] > n {
return -1
}
return f[m][n]
}
图
深度优先
func dfs(graph [][]int, node int, visited []bool) {
visited[node] = true // 标记当前节点为已访问
fmt.Println(node) // 处理当前节点
for _, neighbor := range graph[node] {
if !visited[neighbor] {
dfs(graph, neighbor, visited) // 递归访问未被访问的邻居节点
}
}
}
BFS
func bfs(graph [][]int, start int) {
visited := make([]bool, len(graph))
queue := []int{start} // 将起始节点加入队列
visited[start] = true // 标记起始节点为已访问
for len(queue) > 0 {
node := queue[0] // 从队列前端取出一个节点
queue = queue[1:] // 出队
fmt.Println(node) // 处理节点
for _, neighbor := range graph[node] {
if !visited[neighbor] {
visited[neighbor] = true // 标记为已访问
queue = append(queue, neighbor) // 将未访问的邻居节点加入队列
}
}
}
}