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)  // 将未访问的邻居节点加入队列
            }
        }
    }
}
posted @ 2024-06-30 16:16  叒狗  阅读(56)  评论(0编辑  收藏  举报