Day-8
字典中.get()用法
python字典的get方法會返回指定鍵的值,dict.get(‘鍵’),返回“鍵”對應的“值”,如果鍵不在字典中則返回默認值None。
如果鍵不在字典中,想要自己設置返回值,可以這樣處理,例如dict.get(‘鍵’,‘never’),鍵在字典中,則返回鍵對應的值,鍵不在字典中,則返回never。
dict.items()用法
python字典(Dictionary) items() 函數以列表返回可遍歷的(鍵, 值) 元組數組。
返回值:返回可遍歷的(鍵, 值) 元組數組。
dict = {?'Google':?'www.google.com',?'Runoob':?'www.runoob.com',?'taobao':?'www.taobao.com'}
print(?"字典值 :",dict.items())
for?key,values?in?dict.items():
print(key,values)
結果:
字典值 : dict_items([(?'Google',?'www.google.com'), (?'Runoob',?'www.runoob.com'), (?'taobao',?'www.taobao.com')])
Google www.google.com
taobao www.taobao.com
Runoob www.runoob.com
相關樹的知識點?
樹是一種數據結構,比如:目錄結構。?
樹是由n個節點組成的集合:
? ? ? ? n = 0,那么是一顆空樹;
? ? ? ? n > 0, 那么存在一個節點為樹的根節點,其他節點可分為m個子集,每個子集又為一棵子樹。
關于樹的一些概念:
根節點:例 A
葉子節點:不能分叉的節點,例 B
樹的深度:4 (共有4層)
節點的度:節點有幾個分支,(有兩個孩子節點,那么度為2)
樹的度:節點度的最大值。A有6個分支,為此樹中節點最大的度,所以此樹的度為6.
孩子節點/父節點:例A-父節點,B,C,D,E,F,G--子節點 或者 E---父節點,I J子節點
子樹:E,I,J,P,Q(下圖中紅色圈出)
二叉樹:
二叉樹定義:度不超過2的樹。每個節點最多有兩個孩子節點,兩個孩子節點被區分為左孩子節點和右孩子節點。
滿二叉樹:一個二叉樹,如果每一層的節點數都達到了最大值,那么這個二叉樹就是滿二叉樹。
完全二叉樹:葉子節點只能出現在最下層和次下層,并且最下面一層的節點都集中在該層的最左邊。
?例下圖:(a)滿二叉樹;(b)完全二叉樹;(c)(d)非完全二叉樹。
堆:
定義:一種特殊的完全二叉樹結構
? ? ? ? 大根堆:一棵完全二叉樹,滿足任意節點都比起孩子節點大
? ? ? ? 小根堆:一棵完全二叉樹,滿足任意節點都比起孩子節點小
優先隊列 :
import heapq
pqueue = []
heapq.heappush(pqueue,(0,"A"))
heapq.heappush(pqueue,(2,"B"))
heapq.heappush(pqueue,(10,"C"))
heapq.heappush(pqueue,(6,"D"))
heapq.heappush(pqueue,(15,"E"))
print(pqueue)
"""
result:
?? ?[(0, 'A'), (2, 'B'), (10, 'C'), (6, 'D'), (15, 'E')]
"""
上面是我給優先隊列里面添加元素,下面我們從優先隊列里面彈出元素,請看
print(heapq.heappop(pqueue))
print(heapq.heappop(pqueue))
print(heapq.heappop(pqueue))
print(heapq.heappop(pqueue))
print(heapq.heappop(pqueue))
"""
results:
?? ?(0, 'A')
?? ?(2, 'B')
?? ?(6, 'D')
?? ?(10, 'C')
?? ?(15, 'E')
"""
這里彈出的順序,就是按照優先隊列里面元素對應權值的大小彈出的。
前 K 個高頻元素
給定一個非空的整數數組,返回其中出現頻率前 k 高的元素。
示例 1:
- 輸入: nums = [1,1,1,2,2,3], k = 2
- 輸出: [1,2]
示例 2:
- 輸入: nums = [1], k = 1
- 輸出: [1]
提示:
- 你可以假設給定的 k 總是合理的,且 1 ≤ k ≤ 數組中不相同的元素的個數。
- 你的算法的時間復雜度必須優于 $O(n \log n)$ , n 是數組的大小。
- 題目數據保證答案唯一,換句話說,數組中前 k 個高頻元素的集合是唯一的。
- 你可以按任意順序返回答案。
這道題目主要涉及到如下三塊內容:
這個題使用了優先隊列,用小根堆,這樣的話將頻率小的排除,剩下k個。?
class Solution:def topKFrequent(self, nums: List[int], k: int) -> List[int]:#要統計元素出現頻率map_ = {} #nums[i]:對應出現的次數for i in range(len(nums)):map_[nums[i]] = map_.get(nums[i], 0) + 1#對頻率排序#定義一個小頂堆,大小為kpri_que = [] #小頂堆#用固定大小為k的小頂堆,掃描所有頻率的數值for key, freq in map_.items():heapq.heappush(pri_que, (freq, key))if len(pri_que) > k: #如果堆的大小大于了K,則隊列彈出,保證堆的大小一直為kheapq.heappop(pri_que)#找出前K個高頻元素,因為小頂堆先彈出的是最小的,所以倒序來輸出到數組result = [0] * kfor i in range(k-1, -1, -1):result[i] = heapq.heappop(pri_que)[1]return result二叉樹理論基礎篇?
二叉樹的種類
在我們解題過程中二叉樹有兩種主要的形式:滿二叉樹和完全二叉樹。
滿二叉樹:如果一棵二叉樹只有度為0的結點和度為2的結點,并且度為0的結點在同一層上,則這棵二叉樹為滿二叉樹。
這棵二叉樹為滿二叉樹,也可以說深度為k,有2^k-1個節點的二叉樹。
完全二叉樹:在完全二叉樹中,除了最底層節點可能沒填滿外,其余每層節點數都達到最大值,并且最下面一層的節點都集中在該層最左邊的若干位置。若最底層為第 h 層,則該層包含 1~ 2^(h-1) 個節點。
二叉搜索樹
二叉搜索樹是有數值的了,二叉搜索樹是一個有序樹。
- 若它的左子樹不空,則左子樹上所有結點的值均小于它的根結點的值;
- 若它的右子樹不空,則右子樹上所有結點的值均大于它的根結點的值;
- 它的左、右子樹也分別為二叉排序樹
平衡二叉搜索樹
平衡二叉搜索樹:又被稱為AVL(Adelson-Velsky and Landis)樹,且具有以下性質:它是一棵空樹或它的左右兩個子樹的高度差的絕對值不超過1,并且左右兩個子樹都是一棵平衡二叉樹。
二叉樹的存儲方式?
二叉樹可以鏈式存儲,也可以順序存儲。
那么鏈式存儲方式就用指針, 順序存儲的方式就是用數組。
顧名思義就是順序存儲的元素在內存是連續分布的,而鏈式存儲則是通過指針把分布在各個地址的節點串聯一起。
鏈式存儲如圖:
順序儲存
用數組來存儲二叉樹如何遍歷的呢?
如果父節點的數組下標是 i,那么它的左孩子就是 i * 2 + 1,右孩子就是 i * 2 + 2。
但是用鏈式表示的二叉樹,更有利于我們理解,所以一般我們都是用鏈式存儲二叉樹。
所以大家要了解,用數組依然可以表示二叉樹。
二叉樹的遍歷方式
二叉樹主要有兩種遍歷方式:
- 深度優先遍歷
- 前序遍歷(遞歸法,迭代法)
- 中序遍歷(遞歸法,迭代法)
- 后序遍歷(遞歸法,迭代法)
- 廣度優先遍歷
- 層次遍歷(迭代法)
這里前中后,其實指的就是中間節點的遍歷順序,只要大家記住 前中后序指的就是中間節點的位置就可以了。
看如下中間節點的順序,就可以發現,中間節點的順序就是所謂的遍歷方式
- 前序遍歷:中左右
- 中序遍歷:左中右
- 后序遍歷:左右中
大家可以對著如下圖,看看自己理解的前后中序有沒有問題。
二叉樹的定義
class TreeNode:def __init__(self, value):self.value = valueself.left = Noneself.right = None二叉樹的遞歸遍歷?
每次寫遞歸,都按照這三要素來寫,可以保證大家寫出正確的遞歸算法!
確定遞歸函數的參數和返回值:?確定哪些參數是遞歸的過程中需要處理的,那么就在遞歸函數里加上這個參數, 并且還要明確每次遞歸的返回值是什么進而確定遞歸函數的返回類型。
確定終止條件:?寫完了遞歸算法, 運行的時候,經常會遇到棧溢出的錯誤,就是沒寫終止條件或者終止條件寫的不對,操作系統也是用一個棧的結構來保存每一層遞歸的信息,如果遞歸沒有終止,操作系統的內存棧必然就會溢出。
確定單層遞歸的邏輯:?確定每一層遞歸需要處理的信息。在這里也就會重復調用自己來實現遞歸的過程。
二叉樹的迭代遍歷?
前序遍歷
前序遍歷是中左右,每次先處理的是中間節點,那么先將根節點放入棧中,然后將右孩子加入棧,再加入左孩子。
為什么要先加入 右孩子,再加入左孩子呢? 因為這樣出棧的時候才是中左右的順序。
?中序遍歷
為了解釋清楚,我說明一下 剛剛在迭代的過程中,其實我們有兩個操作:
分析一下為什么剛剛寫的前序遍歷的代碼,不能和中序遍歷通用呢,因為前序遍歷的順序是中左右,先訪問的元素是中間節點,要處理的元素也是中間節點,所以剛剛才能寫出相對簡潔的代碼,因為要訪問的元素和要處理的元素順序是一致的,都是中間節點。
那么再看看中序遍歷,中序遍歷是左中右,先訪問的是二叉樹頂部的節點,然后一層一層向下訪問,直到到達樹左面的最底部,再開始處理節點(也就是在把節點的數值放進result數組中),這就造成了處理順序和訪問順序是不一致的。
那么在使用迭代法寫中序遍歷,就需要借用指針的遍歷來幫助訪問節點,棧則用來處理節點上的元素。
后序遍歷
再來看后序遍歷,先序遍歷是中左右,后續遍歷是左右中,那么我們只需要調整一下先序遍歷的代碼順序,就變成中右左的遍歷順序,然后在反轉result數組,輸出的結果順序就是左右中了?
?
?
# 前序遍歷-迭代-LC144_二叉樹的前序遍歷 class Solution:def preorderTraversal(self, root: TreeNode) -> List[int]:# 根結點為空則返回空列表if not root:return []stack = [root]result = []while stack:node = stack.pop()# 中結點先處理result.append(node.val)# 右孩子先入棧if node.right:stack.append(node.right)# 左孩子后入棧if node.left:stack.append(node.left)return result# 中序遍歷-迭代-LC94_二叉樹的中序遍歷 class Solution:def inorderTraversal(self, root: TreeNode) -> List[int]:if not root:return []stack = [] # 不能提前將root結點加入stack中result = []cur = rootwhile cur or stack:# 先迭代訪問最底層的左子樹結點if cur: stack.append(cur)cur = cur.left # 到達最左結點后處理棧頂結點 else: cur = stack.pop()result.append(cur.val)# 取棧頂元素右結點cur = cur.right return result# 后序遍歷-迭代-LC145_二叉樹的后序遍歷 class Solution:def postorderTraversal(self, root: TreeNode) -> List[int]:if not root:return []stack = [root]result = []while stack:node = stack.pop()# 中結點先處理result.append(node.val)# 左孩子先入棧if node.left:stack.append(node.left)# 右孩子后入棧if node.right:stack.append(node.right)# 將最終的數組翻轉return result[::-1]總結
- 上一篇: 网站的验证码有什么作用?
- 下一篇: 全国计算机排名2012,[教育·计算机]