日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

[Leedcode][JAVA][第94/144/145题][前中后序遍历][递归][迭代][二叉树]

發(fā)布時(shí)間:2023/12/10 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [Leedcode][JAVA][第94/144/145题][前中后序遍历][递归][迭代][二叉树] 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

【問(wèn)題描述】[]

  • 前序遍歷 先輸出當(dāng)前結(jié)點(diǎn)的數(shù)據(jù),再依次遍歷輸出左結(jié)點(diǎn)和右結(jié)點(diǎn)

  • 中序遍歷 先遍歷輸出左結(jié)點(diǎn),再輸出當(dāng)前結(jié)點(diǎn)的數(shù)據(jù),再遍歷輸出右結(jié)點(diǎn)
  • 后續(xù)遍歷 先遍歷輸出左結(jié)點(diǎn),再遍歷輸出右結(jié)點(diǎn),最后輸出當(dāng)前結(jié)點(diǎn)的數(shù)據(jù)

【解答思路】

遞歸 /迭代(棧)
時(shí)間復(fù)雜度:O(N) 空間復(fù)雜度:O(N)

1. 前序遍歷

1.1 遞歸
二叉樹(shù)遍歷(前序、中序、后序)的遞歸方法,唯一改變的是記錄節(jié)點(diǎn)值操作的位置

class Solution {public List<Integer> preorderTraversal(TreeNode root) {if (root != null) {res.add(root.val);preorderTraversal(root.left);preorderTraversal(root.right);}return res;} }

1.2 迭代(棧)
需要一個(gè)輔助棧

class Solution { public List<Integer> preorderTraversal(TreeNode root) {List<Integer> list = new ArrayList<>();Stack<TreeNode> stack = new Stack<>();TreeNode cur = root;while (cur != null || !stack.isEmpty()) {while (cur != null) {//立馬加入當(dāng)前值list.add(cur.val);stack.push(cur);cur = cur.left; //考慮左子樹(shù)}//節(jié)點(diǎn)為空,就出棧cur = stack.pop();//考慮右子樹(shù)cur = cur.right;}return list; }}
2. 中序遍歷

1.1 遞歸
二叉樹(shù)遍歷(前序、中序、后序)的遞歸方法,唯一改變的是記錄節(jié)點(diǎn)值操作的位置

class Solution {List<Integer> res = new ArrayList<>();public List<Integer> inorderTraversal(TreeNode root) {if (root != null) {inorderTraversal(root.left);res.add(root.val);inorderTraversal(root.right);}return res;} }

1.2 迭代(棧)
需要一個(gè)輔助棧

public List<Integer> inorderTraversal(TreeNode root) {List<Integer> ans = new ArrayList<>();Stack<TreeNode> stack = new Stack<>();TreeNode cur = root;while (cur != null || !stack.isEmpty()) {//節(jié)點(diǎn)不為空一直壓棧while (cur != null) {stack.push(cur);cur = cur.left; //考慮左子樹(shù)}//節(jié)點(diǎn)為空,就出棧cur = stack.pop();//當(dāng)前值加入ans.add(cur.val);//考慮右子樹(shù)cur = cur.right;}return ans; }作者:windliang 鏈接:https://leetcode-cn.com/problems/binary-tree-postorder-traversal/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by--34/ 來(lái)源:力扣(LeetCode) 著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。
3. 后序遍歷

1.1 遞歸
二叉樹(shù)遍歷(前序、中序、后序)的遞歸方法,唯一改變的是記錄節(jié)點(diǎn)值操作的位置

class Solution {List<Integer> res = new ArrayList<>();public List<Integer> postorderTraversal(TreeNode root) {if (root != null) {postorderTraversal(root.left);postorderTraversal(root.right);res.add(root.val);}return res;} }

1.2 迭代(棧)
需要兩個(gè)輔助棧
-從根節(jié)點(diǎn)開(kāi)始依次迭代,彈出棧頂元素輸出到輸出列表中,然后依次壓入它的所有孩子節(jié)點(diǎn),按照從上到下、從左至右的順序依次壓入棧中。

-因?yàn)樯疃葍?yōu)先搜索后序遍歷的順序是從下到上、從左至右,所以需要將輸出列表逆序輸出。

class Solution {List<Integer> res = new ArrayList<>();public List<Integer> postorderTraversal(TreeNode root) {if (root == null) {return res;}LinkedList<TreeNode> stack = new LinkedList<>();LinkedList<TreeNode> stackTemp = new LinkedList<>();stackTemp.push(root);while (!stackTemp.isEmpty()) {TreeNode curNode = stackTemp.pop();//stack壓入stack.push(curNode);if (curNode.left != null) {stackTemp.push(curNode.left);}if (curNode.right != null) {stackTemp.push(curNode.right);}}//逆序while (!stack.isEmpty()) {res.add(stack.pop().val);}return res;} }

1.3 轉(zhuǎn)換思想 后續(xù)轉(zhuǎn)前序 逆轉(zhuǎn)

后序遍歷的順序是 左 -> 右 -> 根。
前序遍歷的順序是 根 -> 左 -> 右,
左右其實(shí)是等價(jià)的,所以我們也可以輕松的寫(xiě)出 根 -> 右 -> 左 的代碼。
然后把 根 -> 右 -> 左 逆序,就是 左 -> 右 -> 根,也就是后序遍歷了。

public List<Integer> postorderTraversal2(TreeNode root) {List<Integer> list = new ArrayList<>();Stack<TreeNode> stack = new Stack<>();TreeNode cur = root;while (cur != null || !stack.isEmpty()) {if (cur != null) {list.add(cur.val);stack.push(cur);cur = cur.right; // 考慮右子樹(shù)} else {// 節(jié)點(diǎn)為空,就出棧cur = stack.pop();// 考慮左子樹(shù)cur = cur.left;}}//翻轉(zhuǎn)Collections.reverse(list);return list; }

1.4 一個(gè)棧

public List<Integer> postorderTraversal(TreeNode root) {if (root == null) return new ArrayList<Integer>();TreeNode node = root;List<Integer> ret = new ArrayList<Integer>();Stack<TreeNode> stack = new Stack<TreeNode>();while(node != null || !stack.isEmpty()) {while (node != null) {stack.push(node);node = node.left;}node = stack.pop();// 后序遍歷// 如果沒(méi)有右孩子或者右孩子被訪問(wèn)過(guò)了 {@Alex Zheng 感謝建議哈~}if (node.right == null || (ret.size() != 0 && ret.get(ret.size() - 1).equals(node.right.val)) ) {ret.add(node.val);node = null;} else {stack.push(node);node = node.right;}}return ret;}鏈接:https://leetcode-cn.com/problems/binary-tree-postorder-traversal/solution/bian-li-tong-jie-by-long_wotu/

【總結(jié)】

1. 前中后序遍歷變化的是[中]的位置,左到右的順序不改變
  • 前序遍歷 中左右
  • 中序遍歷 左中右
  • 后續(xù)遍歷 左右中
2.pop 與 poll 都是取出 LinkedList 的第一個(gè)元素,并將該元素刪除,等效于:removeFirst

不同點(diǎn):兩者的實(shí)現(xiàn)所用數(shù)據(jù)結(jié)構(gòu)不同,

  • poll 是基于隊(duì)列結(jié)構(gòu)實(shí)現(xiàn)的方法,當(dāng)隊(duì)列中沒(méi)有元素時(shí),調(diào)用該方法返回 null
  • pop 是基于棧結(jié)構(gòu)實(shí)現(xiàn)的方法,當(dāng)棧中沒(méi)有元素時(shí),調(diào)用該方法會(huì)發(fā)生異常
3. 遞歸模板

res.add(root.val); 位置動(dòng)態(tài)變化

public List<Integer> preorderTraversal(TreeNode root) {if (root != null) {//先序遍歷 res.add(root.val);preorderTraversal(root.left);//中序遍歷 res.add(root.val);preorderTraversal(root.right);//后序遍歷 res.add(root.val);}return res;}
4. 迭代模板

list.add(cur.val);位置動(dòng)態(tài)變化
前中序可遍歷,后續(xù)遍歷可由前序遍歷修改后逆轉(zhuǎn)

public List<Integer> preorderTraversal(TreeNode root) {List<Integer> list = new ArrayList<>();Stack<TreeNode> stack = new Stack<>();TreeNode cur = root;while (cur != null || !stack.isEmpty()) {while (cur != null) {stack.push(cur);// 先序遍歷 list.add(cur.val);cur = cur.left; }//節(jié)點(diǎn)為空,就出棧cur = stack.pop();// 中序序遍歷 list.add(cur.val);cur = cur.right;//后序遍歷 list.add(cur.val); 需要變得多}return list; }

參考鏈接:https://leetcode.wang/leetcode-145-Binary-Tree-Postorder-Traversal.html

總結(jié)

以上是生活随笔為你收集整理的[Leedcode][JAVA][第94/144/145题][前中后序遍历][递归][迭代][二叉树]的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。