- 题目:二叉树的前序遍历(递归以及非递归方法)
- 难度:Medium
- 思路:递归很简单,非递归需要借助栈来实现
- 代码:
递归代码
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
//递归方法
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<Integer>();
if(root == null){
return result;
}
recursion(root,result);
return result;
}
public void recursion(TreeNode node, List<Integer> list){
if(node == null){
return;
}else{
//先递归左子树,再递归右子树
list.add(node.val);
recursion(node.left, list);
recursion(node.right, list);
}
}
}
非递归代码
public class Solution {
//递归方法
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<Integer>();
if(root == null){
return result;
}
//利用双向链表做栈使用
LinkedList<TreeNode> stack = new LinkedList<>();
stack.push(root);
while(!stack.isEmpty()){
TreeNode node = stack.pop();
result.add(node.val);
//注意:将右子树先压入栈(先序遍历的顺序是先跟节点,再左子树,再右子树)
if(node.right != null){
stack.push(node.right);
}
if(node.left != null){
stack.push(node.left);
}
}
return result;
}
}
- 题目:二叉树的后序遍历(递归与非递归方式)
- 难度:Medium
- 思路:后序遍历的递归方式与前序相似,只需要将跟节点的访问调整到左右子树访问之后;而非递归
- 代码:
递归方法
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
if(root == null){
return result;
}
recursion(root, result);
return result;
}
public void recursion(TreeNode node, List<Integer> list){
if(node == null){
return;
}else{
recursion(node.left, list);
recursion(node.right, list);
list.add(node.val);
}
}
}
非递归方法
public class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
if(root == null){
return result;
}
LinkedList<TreeNode> queue = new LinkedList<>();
queue.offer(root);
TreeNode curr = null;
TreeNode pre = null;
while(!queue.isEmpty()){
curr = queue.peekLast();
//1.当前节点为叶子节点时,该节点需要加入result列表
//2.上一个访问的节点是当前节点的左孩子或者右孩子时,说明该节点的左右子树节点都已经被访问过,该节点也被加入result列表
//对于第2点,可能存在疑问:如果当前节点有两个孩子,应该需要判断它两个孩子都被访问呀?,事实是,我们在入队列的时候是右孩子先入队列,然后左孩子再入队列。curr节点的右孩子等于pre的时候,说明curr节点的左孩子已经被访问了或者curr节点没有左孩子;curr节点的左孩子等于pre的时候,说明curr节点只有左孩子
if((curr.left == null && curr.right == null) ||
(pre != null &&(curr.left == pre || curr.right == pre))){
result.add(curr.val);
pre = queue.pollLast();
}else{
if(curr.right != null){
queue.offer(curr.right);
}
if(curr.left != null){
queue.offer(curr.left);
}
}
}
return result;
}
}
- 题目:中序遍历二叉树(递归和非递归)
- 难度:Medium
- 思路:递归方式遍历与前后序基本一样,只是改变访问根节点的位置;非递归方式,我觉得比较难,主要是想统一三种遍历的代码,对中序遍历来讲,这里使用到一个trick就是将curr.left将入栈之后,就把curr.left设置为null
- 代码:
递归
public class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
if(root == null){
return result;
}
recursion(root, result);
return result;
}
public void recursion(TreeNode node, List<Integer> list){
if(node == null){
return;
}else{
recursion(node.left, list);
list.add(node.val);
recursion(node.right, list);
}
}
}
非递归
public class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
if(root == null){
return result;
}
LinkedList<TreeNode> queue = new LinkedList<>();
queue.offer(root);
TreeNode curr = null;
while(!queue.isEmpty()){
curr = queue.peekLast();
System.out.println("进入while循环");
if(curr.left != null){
queue.offer(curr.left);
curr.left = null;//这个trick非常重要,不然就会死循环
}else{
result.add(curr.val);
curr = queue.pollLast();
if(curr.right != null){
queue.offer(curr.right);
}
}
}
return result;
}
}