LeetCode 把二叉搜尋樹轉換為累加樹
阿新 • • 發佈:2019-09-22
第538題
給定一個二叉搜尋樹(Binary Search Tree),把它轉換成為累加樹(Greater Tree),使得每個節點的值是原來的節點值加上所有大於它的節點值之和。 例如: 輸入: 二叉搜尋樹: 5 / \ 2 13 輸出: 轉換為累加樹: 18 / \ 20 13 來源:力扣(LeetCode) 連結:https://leetcode-cn.com/problems/convert-bst-to-greater-tree
概念
二叉搜尋樹
二叉查詢樹(Binary Search Tree),(又:二叉搜尋樹,二叉排序樹)它或者是一棵空樹,或者是具有下列性質的二叉樹: 若它的左子樹不空,則左子樹上所有結點的值均小於它的根結點的值; 若它的右子樹不空,則右子樹上所有結點的值均大於它的根結點的值; 它的左、右子樹也分別為二叉排序樹。
中序遍歷
中序遍歷(LDR)是二叉樹遍歷的一種,也叫做中根遍歷、中序周遊。在二叉樹中,中序遍歷首先遍歷左子樹,然後訪問根結點,最後遍歷右子樹。
解題思路
- 從定義我們知道,BST的中序遍歷為一個遞增序列
- 我們將中序遍歷倒置(先右子樹,後根節點、再左子樹),即可實現一個遞減序列
- 遍歷該序列,從大往小累加並更新節點值,即可實現累加樹(節點值=原來的節點值加上所有大於它的節點值之和)
程式碼實現
1.遞迴倒置中序遍歷思路實現
//遞迴實現 class Solution1 { public TreeNode convertBST(TreeNode root) { addSum(root, 0); return root; } public int addSum(TreeNode node, int parentVal) { //如果沒有節點了,返回父節點值 if (node == null) { return parentVal; } //累加右邊所有節點值 int rVal = addSum(node.right, parentVal); //當前節點值=右邊所有節點累加值+當前節點值 node.val += rVal; //System.out.println("當前節點值:" + node.val); //累加左邊所有節點值 int lVal = addSum(node.left, node.val); return lVal; } }
2.利用堆疊,去遞迴化實現
//利用堆疊,去遞迴化
class Solution2 {
public TreeNode convertBST(TreeNode root) {
TreeNode oRoot = root;
Stack<TreeNode> stack = new Stack();
int sum = 0;
while (true) {
//右節點入棧
while (root != null) {
stack.push(root);
root = root.right;
}
//如果棧為空退出迴圈
if (stack.empty()) {
break;
}
//否則出棧進入計算
else {
TreeNode node = stack.pop();
//更新節點值
node.val += sum;
//更新sum值
sum = node.val;
//左節點進入[右節點入棧]
root = node.left;
}
}
//返回原樹,此時該樹所有節點已做更新
return oRoot;
}
}
總結
我們通過提交程式碼發現堆疊實現會比遞迴執行效率慢很多,這是因為:
- 尾遞迴被jvm編譯器識別並針對其迭代對應進行優化處理過
- 堆疊實現需要頻繁的push(入棧)、pop(出棧)操作導致效能下降
資料
- 示例原始碼
- 原文地址
- Spring Boot、Spring Cloud 示例學習