二叉树的前中后序遍历

在进行二叉树的前中后序遍历的时候,要先明白前中后序遍历的顺序:
前:根->左->右
中:左->根->右
后:左->右->根
下面实现的两种方法:一种是以递归的形式实现。一种是以迭代的方式实现,两者的区别是迭代显示的掉用 了一个栈。
在使用栈的时候利用栈的弹出特点,进行一个深度的遍历,例如递归调用

preorder(node.left,list); //一直往下深入,直到为叶子节点 preorder(node.right,list); //在左左边深入到叶子开始弹出的时候再往右子树开始

具体步骤看中序遍历代码的注释

前序遍历

  1. /**
  2. * Definition for a binary tree node.
  3. * public class TreeNode {
  4. * int val;
  5. * TreeNode left;
  6. * TreeNode right;
  7. * TreeNode() {}
  8. * TreeNode(int val) { this.val = val; }
  9. * TreeNode(int val, TreeNode left, TreeNode right) {
  10. * this.val = val;
  11. * this.left = left;
  12. * this.right = right;
  13. * }
  14. * }
  15. */
  16. class Solution {
  17. //迭代
  18. public List<Integer> preorderTraversal(TreeNode root){
  19. List<Integer> list = new ArrayList<>();
  20. Deque<TreeNode> stack = new LinkedList<>();
  21. while(root!=null || !stack.isEmpty()){
  22. while(root!=null){
  23. list.add(root.val);
  24. stack.push(root);
  25. root = root.left;
  26. }
  27. root = stack.pop();
  28. root = root.right;
  29. }
  30. return list;
  31. }
  32. /**
  33. * 递归
  34. */
  35. public List<Integer> preorderTraversal(TreeNode root) {
  36. List<Integer> list = new ArrayList<>();
  37. preorder(root,list);
  38. return list;
  39. }
  40. void preorder(TreeNode node,List<Integer> list){
  41. if(node==null) return;
  42. list.add(node.val);
  43. preorder(node.left,list);
  44. preorder(node.right,list);
  45. }
  46. }

中序遍历

  1. /**
  2. * Definition for a binary tree node.
  3. * public class TreeNode {
  4. * int val;
  5. * TreeNode left;
  6. * TreeNode right;
  7. * TreeNode() {}
  8. * TreeNode(int val) { this.val = val; }
  9. * TreeNode(int val, TreeNode left, TreeNode right) {
  10. * this.val = val;
  11. * this.left = left;
  12. * this.right = right;
  13. * }
  14. * }
  15. */
  16. /**
  17. * 中序遍历:左->根->右
  18. * 判断根节点有没有左子树
  19. */
  20. class Solution {
  21. /**
  22. * 使用迭代
  23. */
  24. public List<Integer> inorderTraversal(TreeNode root){
  25. //用来保存值
  26. List<Integer> res = new ArrayList<>();
  27. //显示的栈用来走到最深处再弹出当前root
  28. Deque<TreeNode> stack = new LinkedList<>();
  29. while(root!=null || !stack.isEmpty()){
  30. //走到左节点最深处
  31. while(root!=null){
  32. stack.push(root);
  33. root = root.left;
  34. }
  35. //开始弹出 - 将栈顶元素放入集合中
  36. root = stack.pop();
  37. res.add(root.val);
  38. root = root.right;
  39. }
  40. return res;
  41. }
  42. // 使用递归
  43. public List<Integer> inorderTraversal(TreeNode root) {
  44. List<Integer> res = new ArrayList<>();
  45. de(root,res);
  46. return res;
  47. }
  48. public void de(TreeNode node,List<Integer> res){
  49. // 判断是否为空,为空就返回
  50. if(node == null){
  51. return;
  52. }
  53. // 不为空的话继续遍历改节点的孩子直到为空退出
  54. de(node.left,res);
  55. // 当遍历到左边的底的时候开始添加元素
  56. res.add(node.val);
  57. de(node.right,res);
  58. }
  59. }

后序遍历

  1. /**
  2. * Definition for a binary tree node.
  3. * public class TreeNode {
  4. * int val;
  5. * TreeNode left;
  6. * TreeNode right;
  7. * TreeNode() {}
  8. * TreeNode(int val) { this.val = val; }
  9. * TreeNode(int val, TreeNode left, TreeNode right) {
  10. * this.val = val;
  11. * this.left = left;
  12. * this.right = right;
  13. * }
  14. * }
  15. */
  16. class Solution {
  17. public List<Integer> postorderTraversal(TreeNode root) {
  18. //迭代
  19. List<Integer> res = new ArrayList<>();
  20. Deque<TreeNode> stack = new LinkedList<>();
  21. TreeNode pre = null;
  22. while(root!=null || !stack.isEmpty()){
  23. while(root!=null){
  24. stack.push(root);
  25. root = root.left;
  26. }
  27. root = stack.pop();
  28. if(root.right==null || root.right==pre ){
  29. res.add(root.val);
  30. pre = root;
  31. root = null; //表明访问过
  32. }else{
  33. stack.push(root);
  34. root = root.right;
  35. }
  36. }
  37. return res;
  38. }
  39. }

二叉搜索树的验证

二叉搜索树左子树的值都比根节点小,右子树的值都比根节点大;

  1. class Solution {
  2. public boolean isValidBST(TreeNode root) {
  3. return recur(root,Long.MIN_VALUE,Long.MAX_VALUE);
  4. }
  5. boolean recur(TreeNode node,long l,long r){
  6. if(node==null){return true;}
  7. if(node.val <= l || node.val>=r){
  8. return false;
  9. }
  10. return recur(node.left,l,node.val) && recur(node.right,node.val,r);
  11. }
  12. }

重建二叉树(根据前中序)

前:根->左->右
中:左->根->右
例子

前序遍历 preorder = [3,9,20,15,7] 中序遍历 inorder = [9,3,15,20,7]

思路:根据前序的根节点,找出中序遍历中根节点的索引,索引前面为左子树,后面为右子树,一直递归遍历下去;
通过map来保存中序遍历中的值和索引,通过值找到索引。

// 1:前序中的根索引 2:中序中左孩子开始 3:中序中左边孩子结束
tree.left = recur(root_ind+1,left_ind,i-1); // 1. 参数根=当前根索引加上中序中根索引的前面元素个数+1再减去之前加上的元素(left) tree.right = recur(root_ind+i+1-left_ind,i+1,right_ind);

  1. class Solution {
  2. //用来保存中序遍历中查找根节点的索引
  3. HashMap<Integer,Integer> map = new HashMap<>();
  4. int[] preorder;
  5. public TreeNode buildTree(int[] preorder, int[] inorder) {
  6. this.preorder = preorder;
  7. int len = inorder.length;
  8. for(int i = 0;i<len;i++){
  9. map.put(inorder[i],i);
  10. }
  11. return recur(0,0,len-1);
  12. }
  13. TreeNode recur(int root_ind,int left_ind,int right_ind){
  14. if(left_ind>right_ind) return null; // 终止条件
  15. TreeNode tree = new TreeNode(preorder[root_ind]); // 根节点
  16. int i = map.get(preorder[root_ind]); // 获取在中序数组中根节点的索引位置
  17. // 1:前序中的根索引 2:中序中左孩子开始 3:中序中左边孩子结束
  18. tree.left = recur(root_ind+1,left_ind,i-1);
  19. // 1. 参数根=当前根索引加上中序中根索引的前面元素个数+1再减去之前加上的元素(left)
  20. tree.right = recur(root_ind+i+1-left_ind,i+1,right_ind);
  21. return tree;
  22. }
  23. }

路径总和

给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。
image.png
在路径和中,把当前值放到集合中的时候,如果匹配不正确,需要将元素进行删除。

  1. class Solution {
  2. //官方
  3. List<List<Integer>> ret = new LinkedList<List<Integer>>();
  4. Deque<Integer> path = new LinkedList<Integer>();
  5. public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
  6. dfs(root, targetSum);
  7. return ret;
  8. }
  9. public void dfs(TreeNode root, int targetSum) {
  10. if (root == null) {
  11. return;
  12. }
  13. path.offerLast(root.val);
  14. targetSum -= root.val;
  15. if (root.left == null && root.right == null && targetSum == 0) {
  16. ret.add(new LinkedList<Integer>(path));
  17. }
  18. dfs(root.left, targetSum);
  19. dfs(root.right, targetSum);
  20. path.pollLast();
  21. }
  22. //自己写的
  23. List<List<Integer>> res = new ArrayList<>();
  24. List<Integer> cur = new LinkedList<>();
  25. public List<List<Integer>> pathSum(TreeNode root,int targetSum) {
  26. dfs(root,targetSum);
  27. return res;
  28. }
  29. void dfs(TreeNode node, int targetSum){
  30. if(node==null){
  31. return;
  32. }
  33. cur.add(node.val);
  34. targetSum -= node.val;
  35. if(node.left==null && node.right==null && 0==targetSum){
  36. res.add(new ArrayList<Integer>(cur));
  37. cur.remove(cur.size()-1);
  38. return;
  39. }
  40. dfs(node.left,targetSum);
  41. dfs(node.right,targetSum);
  42. cur.remove(cur.size()-1);
  43. }
  44. }