我的 Go 演算法之旅

chenlixin發表於2021-08-26

記錄自己使用Go學演算法的過程 GITHUB地址

Part 1 (TODO:muscle:)

  • 陣列

    • 合併有序陣列(Easy)
    • 刪除有序陣列中的重複項(Easy)
    • 移動零(Easy)
  • 連結串列

    • 反轉連結串列(Easy)
    • K 個一組翻轉連結串列(Hard)
    • 鄰值查詢(Medium)(ACWing)
    • 環形連結串列(Medium)
    • 環形連結串列 II (Medium)
  • 棧、佇列

    • 有效的括號(Medium)
    • 最小棧(Medium)
    • 逆波蘭表示式求值(Medium)
    • 基本計算器 (Hard)
  • 字首和、差分

    • 統計「優美子陣列」(Medium)
    • 二維區域和檢索 - 矩陣不可變(Medium)
    • 航班預訂統計(Medium)
    • 最大子序和(Easy)
  • 雙指標掃描、滑動視窗

    • 兩數之和(Easy)
    • 兩數之和 II - 輸入有序陣列(Easy)
    • 三數之和(Medium)
    • 盛最多水的容器(Medium)
  • 單調棧、單調佇列

    • 柱狀圖中最大的矩形(Hard)
    • 滑動視窗最大值(Hard)
    • 接雨水(Hard)
  • 隨機練習

    • 加一(Easy)
    • 合併兩個有序連結串列(Easy)
    • 設計迴圈雙端佇列(Medium)
    • 和為 K 的子陣列(Medium)

Part 2

  • 雜湊表、集合、對映

    • 兩數之和
    • 字母異位詞分組
    • 串聯所有單詞的子串
  • LRU

    • LRU 快取機制
  • 遞迴

    • 子集
    • 組合
    • 全排列
    • 翻轉二叉樹
    • 驗證二叉搜尋樹
    • 二叉樹的最大深度
    • 二叉樹的最小深度
  • 分治

    • Pow(x, n)
    • 括號生成
  • 隨機練習

    • LRU 快取機制(Medium)
    • 子域名訪問計數(Easy)
    • 陣列的度(Easy)
    • 元素和為目標值的子矩陣數量(Hard)
    • 合併K 個升序連結串列(Hard) (要求:用分治實現,不要用堆)

Part 3

Part 4

  • 二叉堆

  • 二叉搜尋樹

    • 二叉搜尋樹中的插入操作(Medium)
    • 後繼者(Medium)
    • 刪除二叉搜尋樹中的節點(Medium)
    • 把二叉搜尋樹轉換為累加樹(Medium)TODO
  • 二分查詢

    • 二分查詢(Easy)
    • 在排序陣列中查詢元素的第一個和最後一個位置(Medium)
    • x 的平方根(Easy)
    • 搜尋二維矩陣(Medium)
    • 尋找旋轉排序陣列中的最小值(Medium)
  • 三分查詢

    • 尋找峰值(Medium)TODO
    • 猜數字大小(Easy)TODO
    • 分割陣列的最大值(Hard)
    • 製作 m 束花所需的最少天數(Medium)
  • 隨機練習

    • 設計推特(Medium)
    • 資料流的中位數(Hard)
      • 簡單排序
      • 大頂堆小頂堆
    • 尋找旋轉排序陣列中的最小值 II (Hard)

Part 5

  • 排序

    • 初級排序演算法

      • 選擇排序(該放哪個數了)
      • 插入排序(這個數該放哪)
      • 氣泡排序
    • 重要排序演算法

      • 堆排序(Heap Sort是對選擇排序的優化,利用二叉堆高效選出最小值)TODO
      • 希爾排序(Shell Sort是對插入排序的優化)TODO
      • 歸併排序(基於分治,先排序左右子陣列,然後合併兩個有序陣列)
      • 快速排序(基於分治,先調配出左右子陣列,然後對左右子陣列分別進行排序)
        • 不帶pivot
        • 帶pivot
    • 非比較類排序

      • 計數排序
      • 桶排序
      • 基數排序
    • 習題

      • 排序陣列(Medium)
      • 陣列的相對排序
      • 合併區間(Medium)
        • 雙關鍵字快排
        • 差分思想 TODO
      • 陣列中的第 K 個最大元素(Medium)
        • 大根堆
      • 貨倉選址 TODO
      • 翻轉對(Hard)
        • 歸併排序 + 計算
  • 貪心

    • 零錢兌換(Medium)TODO
    • 檸檬水找零(Easy)
    • 分發餅乾(Easy)
    • 買賣股票的最佳時機 II (Easy)
    • 跳躍遊戲 II (Medium)
    • 完成所有任務的最少初始能量(Hard)(貪心證明過程)
  • 隨機練習

    • 在 D 天內送達包裹的能力(Medium)
      • 二分答案
    • 線上選舉(Medium)TODO
    • 愛吃香蕉的珂珂(Medium)
      • 二分答案
    • 區間和的個數(Hard)TODO

Part 6

  • 動態規劃一

    • 零錢兌換(Medium)
    • 不同路徑 II (Medium)
    • 最長公共子序列(Medium)
    • 最長遞增子序列(Medium)
    • 最大子序和(Easy)
    • 乘積最大子陣列(Medium)TODO
  • 動態規劃二

    • 買賣股票系列問題(附帶詳細註釋)

      • 買賣股票的最佳時機(Easy)
        • 注意題目只允許買入一次,也就是說之前沒有買入也沒有賣出過
      • 買賣股票的最佳時機 II(Easy)
        • 注意題目沒有限制買入賣出的次數,但是仍要遵守先買入才能賣出
      • 買賣股票的最佳時機 III(Easy)
        • 注意題目限制完整交易的次數為2,買入前必須賣掉之前的股票
      • 買賣股票的最佳時機 IV (Hard)
        • 注意題目限制完整交易的次數為k,買入前必須賣掉之前的股票
      • 買賣股票的最佳時機含手續費(Medium)
        • 注意題目不限制交易次數,套用買賣股票二的模版即可,買入時減去fee
      • 最佳買賣股票時機含冷凍期(Medium)
        • 注意題目不限制交易次數,買入前必須賣掉之前的股票
        • 與股票三、四對比,同樣是三個狀態,但是決策上要根據冷凍期進行調整
    • 線性DP問題

      • 打家劫舍(Medium)
      • 打家劫舍 II - 環形DP (Medium)
        • 對比打家劫舍1,第一間屋子可偷可不偷,搜兩遍比較大小
      • 編輯距離:fire:(Hard)
        • dp[i][j] word1 前 i 個字元轉換成 word2 前 j 個字元所使用的的最少步數(已達成時)
    • 揹包問題

      • 分割等和子集(Medium)
      • 零錢兌換 II (Medium)
        • 完全揹包模型 + 計數
  • 隨機練習

    • 爬樓梯(Easy)
    • 三角形最小路徑和(Medium)
    • 最長遞增子序列的個數(Medium)TODO
    • 完全平方數(Medium)
      • 完全平方數就是物品(可以無限件使用),湊個正整數n就是揹包,問湊滿這個揹包最少有多少物品?
    • 跳躍遊戲(Medium)
    • 跳躍遊戲 II (Medium)
      • 貪心
      • DP
        f[i] 為到達第 i 個位置所需要的最少步數
        當我們要求某一個 f[i] 的時候,我們需要找到最早能夠經過一步到達 i 點的 j 點
        即有狀態轉移方程:f[i] = f[j] + 1

Part 7

  • DP的優化

  • 區間DP

    • 戳氣球(Hard)
    • 合併石頭的最低成本(Hard)
  • 樹形DP

    • 打家劫舍 III (Medium)
  • 字典樹

    • 實現 Trie (字首樹) (Medium)
      • Trie 樹的核心思想是空間換時間;
        無論儲存樹的結構、字符集陣列還是字符集對映,都需要額外的空間;
        利用字串的公共字首來降低查詢時間的開銷以達到提高效率的目的;
        分組思想–字首相同的字串在同一子樹中;
    • 單詞搜尋 II (Hard)
  • 並查集

    • 模版

      type DisjointSet struct {
        fa []int
      }
      
      // MakeSet(s)
      // 建立一個新的並查集,其中包含s個集合,每個集合裡只有一個元素
      func Construct(n int) DisjointSet {
        s := DisjointSet{fa: make([]int, n)}
        for i := 0; i < n; i++ {
            s.fa[i] = i
        }
        return s
      }
      
      // Find(x)
      // 找到元素x所在的集合的代表
      // 該操作也可以用於判斷兩個元素是否位於同一個集合,只要將它們各自的代表比較一下就可以了
      func (s *DisjointSet) Find(x int) int {
        if s.fa[x] != x {
            s.fa[x] = s.Find(s.fa[x])
        }
        return s.fa[x]
      }
      
      // UnionSet(s)
      // 把元素x和元素y所在的集合合併
      // 要求x和y所在的集合不相交,如果相交則無需合併
      func (s *DisjointSet) Join(x, y int) {
        x, y = s.Find(x), s.Find(y)
        if x != y {
            s.fa[x] = y
        }
      }
    • 省份數量(Medium)

    • 被圍繞的區域(Medium)

  • 隨機練習

    • 冗餘連線(Medium)
      • 並查集
      • DFS
    • 島嶼數量(Medium)
      • 並查集
      • DFS

Part 8

  • 最短路 TODO

    • 網路延遲時間(Medium)
    • 閾值距離內鄰居最少的城市(Medium)
    • Dijkstra 求最短路 II (Easy)(ACWing)
  • 最小生成樹 TODO

    • 連線所有點的最小費用(Medium)
  • 字串基礎知識

    • 字串轉換整數 (atoi) (Medium)
  • Rabin Karp字串雜湊演算法

    • 實現 strStr() (Easy)
    • 重複疊加字串匹配(Medium)TODO
  • 迴文串系列

    • 驗證迴文串(Easy)
    • 驗證迴文字串 Ⅱ(Easy)(貪心 + 驗證)
    • 最長迴文子串(Medium)
      • 列舉中點,向兩邊擴充套件,考慮奇偶
      • 二分答案 + RKHash (附帶詳細註解)
  • 字串與動態規劃

    • 正規表示式匹配(Hard)
    • 不同的子序列(Hard)
  • KMP字串模版

    • 實現 strStr()(Easy)TODO
  • 隨機練習 TODO

Part 9

  • 搜尋剪枝

    • 括號生成(Medium)
      • 剪枝:實時維護左右括號的數量,不合法及時停止
    • N 皇后(Hard)
      • 剪枝:維護兩種斜線(行號+列號、行號-列號)的已用值集合,排除造成重複的分支
    • 有效的數獨(Medium)
    • 解數獨(Hard)
      • 遍歷每次找第一個空位置 VS 每次找分支較少的一個空(剪枝)
  • 迭代加深、折半搜尋與雙向搜尋

    • 單詞接龍(Hard)
      • 單向BFS
      • 雙向BFS
  • 啟發式搜尋:A* 演算法

    • 滑動謎題(Hard)
      • 普通BFS
      • A*演算法 TODO
  • 隨機練習

    • 二進位制矩陣中的最短路徑(Medium)
      • BFS
    • 有序集合庫或平衡樹解決 滑動視窗最大值(Hard)
      • 使用內建treeMap
      • 優先佇列
    • 有序集合庫或平衡樹解決 鄰值查詢(Medium)AcWing TODO
    • 設計跳錶(Hard)TODO
    • 普通平衡樹(Medium)AcWing TODO

Part 10 (TODO:muscle:)

END

好多TODO:joy:,加油。

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章