LeetCode 501——二叉搜尋樹中的眾數
阿新 • • 發佈:2021-01-30
技術標籤:LeetCode刷題
一、題目介紹
給定一個有相同值的二叉搜尋樹(BST),找出 BST 中的所有眾數(出現頻率最高的元素)。
假定 BST 有如下定義:
結點左子樹中所含結點的值小於等於當前結點的值
結點右子樹中所含結點的值大於等於當前結點的值
左子樹和右子樹都是二叉搜尋樹
例如:
給定 BST [1,null,2,2],
1
\
2
/
2
返回[2].
提示:如果眾數超過1個,不需考慮輸出順序
進階:你可以不使用額外的空間嗎?(假設由遞迴產生的隱式呼叫棧的開銷不被計算在內)
來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/find-mode-in-binary-search-tree
二、解題思路
參考官方題解,使用Mirrors中序遍歷的方法。該方法的重點是為當前節點cur建立前驅節點pre,根據中序遍歷的特點(先遍歷左子樹,再遍歷當前節點,左後在遍歷右子樹),需將當前節點的左子樹中最右邊的節點(即中序遍歷最後訪問到的節點)設定為前驅節點,並且令pre->right = cur。這樣當遍歷完當前節點的左子樹時,可以通過pre訪問到cur。具體實現流程如下:
Morris 中序遍歷的一個重要步驟就是尋找當前節點的前驅節點,並且 Morris 中序遍歷尋找下一個點始終是通過轉移到right 指標指向的位置來完成的。
- 如果當前節點沒有左子樹,則遍歷這個點,然後跳轉到當前節點的右子樹。
- 如果當前節點有左子樹,那麼它的前驅節點一定在左子樹上,我們可以在左子樹上一直向右行走,找到當前點的前驅節點。
(1)如果前驅節點沒有右子樹,就將前驅節點的right 指標指向當前節點。這一步是為了在遍歷完前驅節點後能找到前驅節點的後繼,也就是當前節點。
(2)如果前驅節點的右子樹為當前節點,說明前驅節點已經被遍歷過並被修改了right 指標,這個時候我們重新將前驅的右孩子設定為空,遍歷當前的點,然後跳轉到當前節點的右子樹。
三、解題程式碼
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: int count = 0, maxCount = 0, base; vector<int> res; void update(int val) { if(val == base) count++; else { count = 1; //更新計數 base = val;//更新記錄的值 } if(count == maxCount) { res.push_back(base); } else if(count > maxCount) { maxCount = count; res = vector<int> {base}; } } vector<int> findMode(TreeNode* root) { //mirrors中序遍歷 TreeNode* cur = root; TreeNode* pre = NULL; while(cur) { if(!cur->left) //如果當前節點的左子樹為空 { update(cur->val); //遍歷當前節點 cur = cur->right; //開始訪問當前節點的右子樹 continue; } //當前節點左子樹不為空時 pre = cur->left; //需要在當前節點的左子樹中尋找其前驅節點 while(pre->right && pre->right != cur) //在當前節點的左子樹的右下邊找其前驅節點 pre = pre->right; if(!pre->right) { pre->right = cur; cur = cur->left; } else { pre->right = NULL; update(cur->val); cur = cur->right; } } return res; } };