给你二叉树的根节点 root
,返回它节点值的 前序、中序、后序 遍历。
对应的中序、后序结果分别为 [1,3,2] 和 [3,2,1]
解题方法:①递归法、②各自为营的迭代法(每种都有自己的特点,不具有模板性)、③模板迭代
①递归法
前序:
class Solution {
public List preorderTraversal(TreeNode root) {
List res = new LinkedList();
dfs(root,res);
return res;
}
private void dfs(TreeNode root ,List res){
if(root == null){
return;
}
res.add(root.val);
dfs(root.left,res);
dfs(root.right,res);
}
}
中序:
class Solution {
public List inorderTraversal(TreeNode root) {
ArrayList res = new ArrayList();
dfs(root,res);
return res;
}
private void dfs(TreeNode root ,List res){
if(root == null){
return;
}
dfs(root.left,res);
res.add(root.val);
dfs(root.right,res);
}
}
后序:
class Solution {
public List postorderTraversal(TreeNode root) {
List res = new ArrayList();
dfs(root,res);
return res;
}
private void dfs(TreeNode root , List res){
if(root == null){
return;
}
dfs(root.left,res);
dfs(root.right,res);
res.add(root.val);
}
}
②各自为营的迭代法(每种都有自己的特点,不具有模板性)
前序:
class Solution {
public List preorderTraversal(TreeNode root) {
List res = new LinkedList();
Stack stack = new Stack();
if(root == null){
return res;
}
stack.push(root);
while(!stack.isEmpty()){
TreeNode node = stack.pop();
res.add(node.val);
if(node.right != null){
stack.push(node.right);
}
if(node.left != null){
stack.push(node.left);
}
}
return res;
}
}
中序:
class Solution {
public List inorderTraversal(TreeNode root) {
List res = new LinkedList();
Stack stack = new Stack();
if(root == null){
return res;
}
//需要使用指针cur,来解决访问节点和处理节点不一致的问题
TreeNode cur = root;
while(cur != null || !stack.isEmpty()){
if(cur != null){
stack.push(cur);
cur = cur.left;
}else{
cur = stack.pop();
res.add(cur.val);
cur = cur.right;
}
}
return res;
}
}
后序:
class Solution {
//迭代1:各自为营的迭代(前序和后序有一点点关系)把 中左右——>中右左——>翻转成为 左右中(后序)
public List postorderTraversal(TreeNode root) {
List res = new ArrayList();
Stack stack = new Stack();
if(root == null){
return res;
}
stack.push(root);
while(!stack.isEmpty()){
TreeNode node = stack.pop();
res.add(node.val);
if(node.left != null){
stack.push(node.left);
}
if(node.right != null){
stack.push(node.right);
}
}
Collections.reverse(res);
return res;
}
}
③模板迭代
前序:
class Solution {
public List preorderTraversal(TreeNode root) {
List res = new LinkedList();
Stack stack = new Stack();
if(root == null){
return res;
}
stack.push(root);
while(!stack.isEmpty()){
TreeNode node = stack.pop();
if(node != null){
if(node.right != null){
stack.push(node.right);
}
if(node.left != null){
stack.push(node.left);
}
stack.push(node);
stack.push(null);
}else{
res.add(stack.pop().val);
}
}
return res;
}
}
中序:
class Solution {
public List inorderTraversal(TreeNode root) {
List res = new LinkedList();
Stack stack = new Stack();
if(root == null){
return res;
}
stack.push(root);
while(!stack.isEmpty()){
TreeNode node = stack.pop();
if(node != null){
if(node.right != null){
stack.push(node.right);
}
stack.push(node);
stack.push(null);
if(node.left != null){
stack.push(node.left);
}
}else{
res.add(stack.pop().val);
}
}
return res;
}
}
后序:
class Solution {
public List postorderTraversal(TreeNode root) {
List res = new ArrayList();
Stack stack = new Stack();
if(root == null){
return res;
}
stack.push(root);
while(!stack.isEmpty()){
TreeNode node = stack.pop();
if(node != null){
stack.push(node);
stack.push(null);
if(node.right != null){
stack.push(node.right);
}
if(node.left != null){
stack.push(node.left);
}
}else{
res.add(stack.pop().val);
}
}
return res;
}
}
总结:模板迭代中,先序、中序、后序遍历只有下面这一块的两行代码有变动,好记、但是不好理解。
①
stack.push(node);
stack.push(null);
②
if(node.right != null){
stack.push(node.right);
}
③
if(node.left != null){
stack.push(node.left);
}
①、②、③三部分根据先序、后序、中序遍历的顺序,那一部分先访问到,就让它最后入栈即可。
模板迭代的整体思想就是,如果访问到 null ,则栈下一个元素就是要弹出来加入结果集的元素。