极客时间 算法训练营 毕业总结
不知不覺(jué)8周的算法訓(xùn)練營(yíng)也接近尾聲,這期間訓(xùn)練營(yíng)對(duì)自己的影響有三方面
- 一方面是收獲了刻意練習(xí),終身成長(zhǎng)這些可以產(chǎn)生長(zhǎng)遠(yuǎn)影響的思想,這里推薦三本書(shū) 卡羅爾·德韋克的《終身成長(zhǎng)》、安德斯·艾利克森和羅伯特·普爾的《刻意練習(xí)》以及彼得·布朗等的《認(rèn)知天性》
- 一方面是在自己對(duì)算法與數(shù)據(jù)結(jié)構(gòu)的態(tài)度與認(rèn)知上,從之前的抗拒和一提到就覺(jué)得很難,到接受和樂(lè)在其中的轉(zhuǎn)變,從算法與數(shù)據(jù)結(jié)構(gòu)大概是這樣,到有一個(gè)脈絡(luò)清晰的知識(shí)結(jié)構(gòu)的轉(zhuǎn)變
- 一方面就是知識(shí)本身,下面將數(shù)據(jù)結(jié)構(gòu)與算法總體回顧下
數(shù)據(jù)結(jié)構(gòu)
一維
- 基礎(chǔ): 數(shù)組 array (string),鏈表 linked list
- 高級(jí): 棧 stack,隊(duì)列 queue,雙端隊(duì)列 deque,集合 set,映射 map (hash or map),etc
涉及題目:
棧 stack: 括號(hào)匹配問(wèn)題、直方圖、接雨水
隊(duì)列 queue: 滑動(dòng)窗口
二維
- 基礎(chǔ): 樹(shù) tree,圖 graph
- 高級(jí): 二叉搜索樹(shù) binary search tree (red-black tree,AVL),堆 heap,并查集 disjoint set,字典樹(shù) Trie,etc
特殊
- 位運(yùn)算 Bitwise,布隆過(guò)濾器 BloomFilter
- LRU Cache
時(shí)間復(fù)雜度圖
https://www.bigocheatsheet.com/
主定理
https://en.wikipedia.org/wiki/Master_theorem_(analysis_of_algorithms)
- 一維數(shù)組二分查找:每次排除一半,故為O(log n)
- 二叉樹(shù)的遍歷:可以理解成每個(gè)節(jié)點(diǎn)被訪(fǎng)問(wèn)且僅訪(fǎng)問(wèn)一次,故為O(n)
- 二維矩陣的二分查找:O(n)
- 歸并排序:O(n logn)
數(shù)據(jù)結(jié)構(gòu)思維導(dǎo)圖
算法
- if-else,switch ——> branch
- for,while loop ——> literation
- 遞歸 Recursion (Divide & Conquer ,Backtrace)
所有高級(jí)算法或數(shù)據(jù)結(jié)構(gòu)最后都會(huì)轉(zhuǎn)換成以上三種
- 搜索 Search:深度優(yōu)先搜索 Depth first search, 廣度優(yōu)先搜索 Breadth first search,A*,etc
- 動(dòng)態(tài)規(guī)劃 Dynamic Programming (遞歸+備忘錄 或 迭代+DP方程)
- 二分查找 Binary Search
- 貪心 Greedy
- 數(shù)學(xué) Math,幾何 Geometry
算法 思維導(dǎo)圖
鏈接:https://pan.baidu.com/s/1FL93CnqsWA0jbHt_ePSpjQ
提取碼:ulud
代碼模板
這里列舉部分模板,其他模板 并查集 Disjoint Set、布隆過(guò)濾器、LRU Cache、初級(jí)排序、特殊排序等模板可以參看之前總結(jié)
遞歸模板
def recursion(level, param1, param2, ...): # 遞歸終止條件if level > MAX_LEVEL: process_result return # 處理當(dāng)前層邏輯process(level, data...) # 往下一層self.recursion(level + 1, p1, ...) # 清理當(dāng)前層分治模板
def divide_conquer(problem, param1, param2, ...): # 遞歸終止條件if problem is None: print_result return # 處理當(dāng)前層邏輯(分解子問(wèn)題)data = prepare_data(problem) subproblems = split_problem(problem, data) # 往下一層(解決子問(wèn)題)subresult1 = self.divide_conquer(subproblems[0], p1, ...) subresult2 = self.divide_conquer(subproblems[1], p1, ...) subresult3 = self.divide_conquer(subproblems[2], p1, ...) …# 合并子結(jié)果(合并結(jié)果)result = process_result(subresult1, subresult2, subresult3, …)# 清理當(dāng)前層歸并排序模板
def merge_sort(arr, left, right):"""歸并排序(Merge Sort)"""if right <= left: # 遞歸終止條件return# 先輸入序列分成兩個(gè)長(zhǎng)度為n/2的子序列并對(duì)這兩個(gè)子序列分別采用歸并排序mid = (left + right) >> 1 # (left + right) / 2merge_sort(arr, left, mid) # 注意 midmerge_sort(arr, mid + 1, right)# 排序好的子序列合, 重點(diǎn) merge 函數(shù)的實(shí)現(xiàn)merge(arr, left, mid, right)def merge(arr, left, mid, right):# left , mid 有序 mid + 1 , right 有序temp = [0 for _ in range( right - left + 1)] # 中間數(shù)組, 需要額外的內(nèi)存空間i = leftj = mid + 1k = 0while i <= mid and j <= right: # 合并 left , mid 有序數(shù)列 和 mid + 1 , right 有序數(shù)列if arr[i] <= arr[j]:temp[k] = arr[i]k, i = k + 1, i + 1else:temp[k] = arr[j]k, j = k + 1, j + 1while i <= mid: # left , mid 有序數(shù)列 剩余temp[k] = arr[i]k, i = k + 1, i + 1while j <= right: # mid + 1 , right 有序數(shù)列 剩余temp[k] = arr[j]k, j = k + 1, j + 1# 將 排序好的 temp 放入 arr 中for p in range(len(temp)):arr[left + p] = temp[p]快速排序模板
def quick_sort(arr, begin, end):"""快速排序(Quick Sort)"""if end <= begin: # 遞歸終止條件return# 先找標(biāo)桿 pivot,將小元素放 pivot左邊,大元素放右側(cè); 重點(diǎn) partition 函數(shù)的實(shí)現(xiàn)pivot = partition(arr, begin, end)# 然后依次對(duì)標(biāo)桿 pivot 右邊和右邊的子數(shù)組繼續(xù)快排quick_sort(arr, begin, pivot-1) # 注意 不包括標(biāo)桿quick_sort(arr, pivot + 1,end)def partition(arr, begin, end):"""partition 函數(shù) 用于查找 標(biāo)桿位置并處理排序數(shù)組"""pivot = end # 選擇 end 為標(biāo)桿min_index = begin # counter: ?于pivot的元素的下標(biāo)for i in range(begin, end): # 這里不包含 標(biāo)桿位置if arr[i] < arr[pivot]: # i 位置數(shù)據(jù) 小于 a[pivot]arr[min_index], arr[i] = arr[i], arr[min_index] # 交換 arr[min_index], arr[i] 數(shù)據(jù)位置min_index += 1 # 遞增# 循環(huán)結(jié)束 min_index 就為 標(biāo)桿應(yīng)該所在位置arr[min_index], arr[pivot] = arr[pivot], arr[min_index]return min_indexDFS 模板
遞歸實(shí)現(xiàn):
#遞歸前處理 visited = set() # 節(jié)點(diǎn)是否被訪(fǎng)問(wèn)def dfs(node,visited):# 遞歸終止條件if node in visited: # 是否被訪(fǎng)問(wèn)return# 遞歸到下一層前處理(當(dāng)前層處理)visited.add(node) # 其它處理# 遞歸到下一層for next_node in node.children(): if not next_node in visited: dfs(next_node, visited)# 遞歸下層次返回后處理迭代實(shí)現(xiàn):
dfs=棧,壓棧,出棧
BFS 模板
迭代實(shí)現(xiàn):
bfs=隊(duì)列,入隊(duì)列,出隊(duì)列
def bfs(graph, start, end):# 迭代前處理queue = [] # 輔助隊(duì)列queue.append([start]) # 入隊(duì)列visited.add(node) # 標(biāo)記訪(fǎng)問(wèn)# 迭代終止條件while queue:# 迭代 node = queue.pop(0) # 出隊(duì)列visited.add(node) # 標(biāo)記訪(fǎng)問(wèn)rocess (node) # 當(dāng)前節(jié)點(diǎn)處理nodes = generate_related_nodes(node) # 生成相關(guān)節(jié)點(diǎn)queue.push(nodes) # 入隊(duì)列# 迭代后處理二分查找代碼模板
left, right = 0, len(array) - 1 while left <= right: # mid = (left + right) / 2mid = low + (high-low)/2if array[mid] == target: # 找到目標(biāo)break or return result elif array[mid] < target: left = mid + 1 else: right = mid - 1Trie樹(shù)模板
class Trie:def __init__(self):self.root = {} # 根節(jié)點(diǎn)self.endofword = "#" # 標(biāo)識(shí)是否是一個(gè)完整的單詞def insert(self, word: str) -> None:# 插入操作node = self.root # 根節(jié)點(diǎn)for char in word: # 遍歷單詞 word 中每個(gè)字符node = node.setdefault(char,{}) # 字典形式依次將字符保存到樹(shù)的每一層中# dict.setdefault(key, default=None) 如果 key 在 字典中,返回對(duì)應(yīng)的值。# 如果不在字典中,則插入 key 及設(shè)置的默認(rèn)值 default,并返回 default ,default 默認(rèn)值為 None。node[self.endofword] = self.endofword # 完整單詞標(biāo)識(shí)def search(self, word: str) -> bool:# 查找操作node = self.rootfor char in word: # 遍歷單詞 word 中每個(gè)字符if char not in node: # 未找到return Falsenode = node.get(char) # 找到進(jìn)入下一結(jié)點(diǎn)return self.endofword in node # 是否為完整的單詞def startsWith(self, prefix: str) -> bool:# 字典樹(shù)中是否有以 prefix 為前綴的單詞node = self.rootfor char in prefix: # 遍歷 前綴 prefixif char not in node:return Falsenode = node.get(char) return True學(xué)習(xí)要點(diǎn)
基本功是區(qū)別業(yè)余和職業(yè)選手的根本。深厚功底來(lái)自于 — 過(guò)遍數(shù)
最大的誤區(qū):只做一遍
五毒神掌
刻意練習(xí) - 練習(xí)缺陷弱點(diǎn)地方、不舒服、枯燥
反饋 - 看題解、看國(guó)際版的高票回答
切題四件套
- Clarification
- Possible Solutions
- compare (time/space)
- optimal (加強(qiáng))
- Coding(多寫(xiě))
- Test cases
五毒神掌
第一遍
五分鐘:讀題 + 思考
直接看解法:多看幾種,比較解法優(yōu)劣
背誦、默寫(xiě)好的解法
第二遍
馬上自己寫(xiě) ——> Leetcode提交
多種解法比較、體會(huì) ——> 優(yōu)化!
第三遍
過(guò)了一天后,再重復(fù)做題
不同解法的熟練程度——>專(zhuān)項(xiàng)練習(xí)
第四遍
過(guò)了一周后:反復(fù)回來(lái)練習(xí)相同的題目
第五遍
面試前一周恢復(fù)性訓(xùn)練
經(jīng)典習(xí)題
爬樓梯: https://leetcode-cn.com/problems/climbing-stairs/
硬幣兌換: https://leetcode-cn.com/problems/coin-change/
有效括號(hào): https://leetcode-cn.com/problems/valid-parentheses/
括號(hào)生成: https://leetcode-cn.com/problems/generate-parentheses/
柱狀圖中最大的矩形: https://leetcode-cn.com/problems/largest-rectangle-in-histogram/
滑動(dòng)窗口最大值: https://leetcode-cn.com/problems/sliding-window-maximum/
二叉樹(shù)遍歷:
- 二叉樹(shù)的層次遍歷:https://leetcode-cn.com/problems/binary-tree-level-order-traversal/
- 二叉樹(shù)的前序遍歷: https://leetcode-cn.com/problems/binary-tree-preorder-traversal/
- 二叉樹(shù)的中序遍歷: https://leetcode-cn.com/problems/binary-tree-inorder-traversal/
- 二叉樹(shù)的后序遍歷: https://leetcode-cn.com/problems/binary-tree-postorder-traversal/
驗(yàn)證二叉搜索樹(shù): https://leetcode-cn.com/problems/validate-binary-search-tree/submissions/
股票買(mǎi)賣(mài):
- 買(mǎi)賣(mài)股票的最佳時(shí)機(jī) IV https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iv/
打家劫舍:
- 打家劫舍 II: https://leetcode-cn.com/problems/house-robber-ii/
編輯距離: https://leetcode-cn.com/problems/edit-distance/
最長(zhǎng)上升子序列: https://leetcode-cn.com/problems/longest-increasing-subsequence/
最長(zhǎng)公共子序列: https://leetcode-cn.com/problems/longest-common-subsequence/
字母異位詞分組: https://leetcode-cn.com/problems/group-anagrams/
回文串:
- 最長(zhǎng)回文子串: https://leetcode-cn.com/problems/longest-palindromic-substring/
通配符匹配: https://leetcode-cn.com/problems/wildcard-matching/
高級(jí)數(shù)據(jù)結(jié)構(gòu)(Trie、 BloomFilter、 LRU cache、 etc)
總結(jié)
以上是生活随笔為你收集整理的极客时间 算法训练营 毕业总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: AutoCAD实用小技巧教程。
- 下一篇: 基于C语言的双人贪吃蛇游戏程序设计