- 二叉树的中序遍历
给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。
示例 1:
输入:root = [1,null,2,3]
输出:[1,3,2]
示例 2:
输入:root = []
输出:[]
示例 3:
输入:root = [1]
输出:[1]
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> ans=new ArrayList<>();
if(root==null)return ans;
List<Integer> l=inorderTraversal(root.left);
List<Integer> r=inorderTraversal(root.right);
ans.addAll(l);
ans.add(root.val);
ans.addAll(r);
return ans;
}
}
迭代
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> ans=new ArrayList<>();
Deque<TreeNode> stk=new LinkedList<>();
while(root!=null||!stk.isEmpty()){
while(root!=null){
stk.push(root);
root=root.left;
}
root=stk.pop();
ans.add(root.val);
root=root.right;
}
return ans;
}
}
Morris 中序遍历
while (predecessor.right != null && predecessor.right != root)的理解:
对于一个节点,需要找到它的pre节点,这时只有两种情况,一种是第一次
来到当前节点,那么pre节点的右孩子肯定是空的,那就直接指向过去,第二种就是第二次回到当前节点的情况,这种情况是就是从当前节点的pre节点的right过来的,那么当前节点的左子树都被遍历完了,那么肯定就是处理当前节点,然后进入右子树了。
官方题解
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
TreeNode predecessor = null;
while (root != null) {
if (root.left != null) {
// predecessor 节点就是当前 root 节点向左走一步,然后一直向右走至无法走为止
predecessor = root.left;
while (predecessor.right != null && predecessor.right != root) {
predecessor = predecessor.right;
}
// 让 predecessor 的右指针指向 root,继续遍历左子树
if (predecessor.right == null) {
predecessor.right = root;
root = root.left;
}
// 说明左子树已经访问完了,我们需要断开链接
else {
res.add(root.val);
predecessor.right = null;
root = root.right;
}
}
// 如果没有左孩子,则直接访问右孩子
else {
res.add(root.val);
root = root.right;
}
}
return res;
}
}
自己的答案
中序
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> ans=new ArrayList<>();
while(root!=null){
if(root.left!=null){
TreeNode pre=root.left;
while(pre.right!=null&&pre.right!=root)pre=pre.right;
if(pre.right==null){
pre.right=root;
root=root.left;
}
else{
//左子树都遍历完了,访问本身,然后进右子树
ans.add(root.val);
root=root.right;
}
}else{
//没有左子树,访问自身后进入右子树
//pre.right = null;
ans.add(root.val);
root=root.right;
}
}
return ans;
}
}
先序
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
while (root != null) {
if (root.left != null) {
TreeNode pre = root.left;
while (pre.right != null && pre.right != root) pre = pre.right;
if (pre.right == null) {
//第一次找到左子树的最右节点,先将自己加入ans,再挂上,相当于标记,然后进入左子树
res.add(root.val);
pre.right = root;
root = root.left;
} else {
//第二次找到左子树的最右节点,此时本节点和左子树都访问完了,直接进入右子树
//pre.right = null;//把挂上去的再取下去,恢复树的结构,但是对答案不影响
root = root.right;
}
} else {
//没有左子树,当然就不要先找了,直接将自己加入答案,然后进入右子树
res.add(root.val);
root = root.right;
}
}
return res;
}
}