LeetCode训练营之二叉树

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/boker_han/article/details/83897508

一、binary-tree-preorder-traversal

Given a binary tree, return the preorder traversal of its nodes’ values.

方法一:递归实现前序遍历

	public ArrayList<Integer> preorderTraversal(TreeNode root) {
        //返回前序遍历结果
        ArrayList<Integer> result = new ArrayList<>();
        //边界值检测
        if(root == null)
            return result;
        //调用递归处理逻辑前序遍历二叉树
        preorderTraversalCore(root,result);
        return result;
    }
    private void preorderTraversalCore(TreeNode root,ArrayList<Integer> result){
        if(root == null)
            return;
        result.add(root.val);
        preorderTraversalCore(root.left,result);
        preorderTraversalCore(root.right,result);
    }

方法二:迭代实现前序遍历(栈)

 	public ArrayList<Integer> preorderTraversal(TreeNode root) {
        //返回的遍历结果
        ArrayList<Integer> result = new ArrayList<>();
        //边界值检验
        if(root == null)
            return result;
        //辅助数据结构——栈,实现递归遍历的操作
        Stack<TreeNode> stack = new Stack<>();
        //首先添加根节点
        stack.push(root);
        //循环进行节点的入栈和出栈,出一进二,进栈顺序右节点先进,左节点后进
        while(stack.size() != 0){ 
            TreeNode cur = stack.pop();
            if(cur.right != null)
                stack.push(cur.right);
            if(cur.left != null)
                stack.push(cur.left);
            result.add(cur.val);
        }
        return result;
    }

二、binary-tree-postorder-traversal

Given a binary tree, return the postorder traversal of its nodes’ values.

方法一:递归实现后序遍历

	public ArrayList<Integer> postorderTraversal(TreeNode root) {
	        //返回结果
	        ArrayList<Integer> result = new ArrayList<>();
	        //边界值校测
	        if(root == null)
	            return result;
	        //调用递归函数后序遍历二叉树
	        postorderTraversalCore(root,result);
	        return result;
	   }
	  //递归逻辑实现二叉树后序遍历
	  private void postorderTraversalCore(TreeNode root,ArrayList<Integer> result){
	        if(root == null)
	            return;
	        postorderTraversalCore(root.left,result);
	        postorderTraversalCore(root.right,result);
	        result.add(root.val);
	  }

方法二:迭代实现后序遍历(两栈)

   public ArrayList<Integer> postorderTraversal(TreeNode root) {
       //返回遍历结果
       ArrayList<Integer> result = new ArrayList<>();
       //边界值检测
       if(root == null)
           return result;
       //辅助栈一:用于保存中间节点
       Stack<TreeNode> stack1 = new Stack<>();
       //辅助栈二:用于保存反序的遍历结果
       Stack<Integer> stack2 = new Stack<>();
       stack1.push(root);
       //第一次遍历二叉树,将树节点按照后序遍历的顺序压入栈2
       while(!stack1.isEmpty()){
           TreeNode cur = stack1.pop();
           if(cur.left != null)
               stack1.push(cur.left);
           if(cur.right != null)
               stack1.push(cur.right);
           stack2.push(cur.val);
       }
       //弹出栈2的节点值到遍历结果线性表中
       while(stack2.size() != 0){
           result.add(stack2.pop());
       }
       return result;
   }

三、binary-tree-inorder-traversal

Given a binary tree, return the inorder traversal of its nodes’ values.

方法一:递归中序遍历二叉树

    public ArrayList<Integer> inorderTraversal(TreeNode root) {
     //返回结果
      ArrayList<Integer> result = new ArrayList<>();
      //边界值校测
      if(root == null)
          return result;
      //调用递归函数中序遍历二叉树
      inorderTraversalCore(root,result);
      return result;
  	}
  	 private void inorderTraversalCore(TreeNode root,ArrayList<Integer> result){
       if(root == null)
           return;
       inorderTraversalCore(root.left,result);
       result.add(root.val);
       inorderTraversalCore(root.right,result);
   }

方法二:迭代中序遍历二叉树(栈)

    public ArrayList<Integer> inorderTraversal(TreeNode root) {
       //返回中序遍历结果
       ArrayList<Integer> result = new ArrayList<>();
       //边界值检测
       if(root == null)
           return result;
       //辅助数据结构,用于模拟中序遍历过程
       Stack<TreeNode> stack = new Stack<>();
       while(!stack.isEmpty() || root != null){
           //走左子树方向深入
           if(root != null){
               stack.push(root);
               root = root.left;
           }else{
               //左子树方向走到底,弹出栈顶元素,并从右子节点向左开始深入
               TreeNode cur = stack.pop();
               result.add(cur.val);
               root = cur.right;
           }
       }
       return result;
   }

四、binary-tree-level-order-traversal

Given a binary tree, return the level order traversal of its nodes’ values. (ie, from left to right, level by level).

   public ArrayList<ArrayList<Integer>> levelOrder(TreeNode root) {
       //返回的层序遍历结果
       ArrayList<ArrayList<Integer>> result = new ArrayList<>();
       //边界值检测
       if(root == null)
           return result;
       //当前层使用的队列
       Queue<TreeNode> queue1 = new LinkedList<>();
       //当前层的层序遍历结果
       queue1.offer(root);
       //保存当前层的遍历结果,并保存下一层的节点队列,依次循环
       while(queue1.size() != 0){
           //存放当前层的层序遍历结果
           ArrayList<Integer> temp = new ArrayList<>();
           //一定要保存当前层的节点数,用于后续的节点出队,和下一层的节点入队
           int len = queue1.size();
           //记录下一层的节点队列
           Queue<TreeNode> queue2 = new LinkedList<>();
           for(int i = 0 ; i < len ; i++){
               TreeNode cur = queue1.poll();
               if(cur.left != null)
                   queue2.offer(cur.left);
               if(cur.right != null)
                   queue2.offer(cur.right);
               temp.add(cur.val);
           }
           result.add(temp);
           queue1 = queue2;
       }
       return result;
   }

五、binary-tree-level-order-traversal

Given a binary tree, return the bottom-up level order traversal of its nodes’ values. (ie, from left to right, level by level from leaf to root).

   public ArrayList<ArrayList<Integer>> levelOrderBottom(TreeNode root) {
       //返回的层序遍历结果
      ArrayList<ArrayList<Integer>> result = new ArrayList<>();
      //边界值检测
      if(root == null)
          return result;
      //当前层使用的队列
      Queue<TreeNode> queue1 = new LinkedList<>();
      //当前层的层序遍历结果
      queue1.offer(root);
      //保存当前层的遍历结果,并保存下一层的节点队列,依次循环
      while(queue1.size() != 0){
          //存放当前层的层序遍历结果
          ArrayList<Integer> temp = new ArrayList<>();
          //一定要保存当前层的节点数,用于后续的节点出队,和下一层的节点入队
          int len = queue1.size();
          //记录下一层的节点队列
          Queue<TreeNode> queue2 = new LinkedList<>();
          for(int i = 0 ; i < len ; i++){
              TreeNode cur = queue1.poll();
              if(cur.left != null)
                  queue2.offer(cur.left);
              if(cur.right != null)
                  queue2.offer(cur.right);
              temp.add(cur.val);
          }
          result.add(temp);
          queue1 = queue2;
      }
       //相比上一题,只多了下面这段代码
      int begin = 0;
      int end = result.size() - 1;
      while(begin < end){
          ArrayList<Integer> temp = result.get(begin);
          result.set(begin,result.get(end));
          result.set(end,temp);
          begin++;
          end--;
      }
      return result;
   }

五、binary-tree-zigzag-level-order-traversal

Given a binary tree, return the zigzag level order traversal of its nodes’ values. (ie, from left to right, then right to left for the next level and alternate between).

	  public ArrayList<ArrayList<Integer>> zigzagLevelOrder(TreeNode root) {
	      //返回的层序遍历结果
	      ArrayList<ArrayList<Integer>> result = new ArrayList<>();
	      //边界值检测
	      if(root == null)
	        return result;
	      //当前层
	      Stack<TreeNode> stack1 = new Stack<>();
	      //下一层
	      Stack<TreeNode> stack2;
	      //当前层的遍历结果
	      ArrayList<Integer> temp;
	      //第一层
	      stack1.push(root);
	      boolean ltr = true;
	      //循环处理每一层
	      while(stack1.size() != 0){
	          temp = new ArrayList<Integer>();
	          stack2 = new Stack<>();
	          //先添加左子节点,再添加右子节点
	           if(ltr){
	               while(stack1.size() != 0){
	                   TreeNode cur = stack1.pop();
	                   if(cur.left != null)
	                       stack2.push(cur.left);
	                   if(cur.right != null)
	                       stack2.push(cur.right);
	                   temp.add(cur.val);
	               }
	           }else{
	               //先添加右子节点,再添加左子节点
	               while(stack1.size() != 0){
	                   TreeNode cur = stack1.pop();
	                   if(cur.right != null)
	                       stack2.push(cur.right);
	                   if(cur.left != null)
	                       stack2.push(cur.left);
	                   temp.add(cur.val);
	               }
	           }
	          //更新当前层的栈
	          stack1 = stack2;
	          //添加当前层的遍历结果到返回结果中
	          result.add(temp);
	          //更新添加子节点方向
	          ltr = !ltr;
	      }
	      return result;
	  }

六、 construct-binary-tree-from-preorder-and-inorder-traversal

Given preorder and inorder traversal of a tree, construct the binary tree.

	  public TreeNode buildTree(int[] preorder, int[] inorder) {
	      //参数合法性校验
	      if(preorder == null || inorder == null || preorder.length != inorder.length)
	          return null;
	      //数组长度,即节点个数
	      int len = preorder.length;
	      //调用递归逻辑实现二叉树重建
	      return buildTreeCore(preorder,0,len-1,inorder,0,len-1);
	  }
	  private TreeNode buildTreeCore(int[] pre,int beginPre,int endPre,int[] in,int beginIn,int endIn){
	      //数组中无元素,已到达叶子结点的叶子结点处
	      if(beginPre > endPre)
	          return null;
	      //在中序数组中找出与当前前序数组的第一个元素,并以此元素的下标进行划分,进一步递归处理左右子树
	      for(int i = beginIn ; i <= endIn ; i++){
	          if(in[i] != pre[beginPre])
	              continue;
	          //当前节点
	          TreeNode node = new TreeNode(pre[beginPre]);
	          //当前节点的左子树
	          node.left = buildTreeCore(pre,beginPre+1,beginPre+i-beginIn,in,beginIn,i-1);
	          //当前节点的右子树
	          node.right = buildTreeCore(pre,beginPre+i-beginIn+1,endPre,in,i+1,endIn);
	          return node;
	      }
	      return null;
	  }

七、construct-binary-tree-from-inorder-and-postorder-traversal

Given inorder and postorder traversal of a tree, construct the binary tree.

   public TreeNode buildTree(int[] inorder, int[] postorder) {
       //参数合法性校验
         if(postorder == null || inorder == null || postorder.length != inorder.length)
             return null;
         //数组长度,即节点个数
         int len = postorder.length;
         //调用递归逻辑实现二叉树重建
         return buildTreeCore(postorder,0,len-1,inorder,0,len-1);
   }
    private TreeNode buildTreeCore(int[] post,int beginPost,int endPost,int[] in,int beginIn,int endIn){
         //数组中无元素,已到达叶子结点的叶子结点处
         if(beginPost > endPost)
             return null;
         //在中序数组中找出与当前后续数组的倒数第一个元素,并以此元素的下标进行划分,进一步递归处理左右子树
         for(int i = beginIn ; i <= endIn ; i++){
             if(in[i] != post[endPost])
                 continue;
             //当前节点
             TreeNode node = new TreeNode(post[endPost]);
             //当前节点的左子树
             node.left = buildTreeCore(post,beginPost,beginPost+i-beginIn-1,in,beginIn,i-1);
             //当前节点的右子树
             node.right = buildTreeCore(post,beginPost+i-beginIn,endPost-1,in,i+1,endIn);
             return node;
         }
         return null;
     }

猜你喜欢

转载自blog.csdn.net/boker_han/article/details/83897508