二叉树递归解题

83.删除排序中的重复元素

难度 简单

给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。

示例1:

  输入: 1->1->2
  输出: 1->2

示例2:

  输入: 1->1->2->3->3
  输出: 1->2->3

Solution

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        if (head == null || head.next == null)
            return head;
        head.next = deleteDuplicates(head.next);
        if (head.val == head.next.val)
            head = head.next;
        return head;
    }
}

101.对称二叉树

难度 简单

给定一个二叉树,检查它是否是镜像对称的。

示例1:

  二叉树 [1,2,2,3,4,4,3] 是对称的。

      1
     / \
    2   2
   / \ / \
  3  4 4  3

示例2:

  [1,2,2,null,3,null,3] 则不是镜像对称的:

      1
     / \
    2   2
     \   \
     3    3

解题思路

  递归问题解决步骤:
  1. 找整个递归的终止条件:递归应该在什么时候结束?
  2. 找到返回值:应该给上一级返回什么信息?
  3. 本级递归应该做什么:在这一级递归中,应该完成什么任务?
  [参考博客](https://lyl0724.github.io/2020/01/25/1/)

在这个题目中,目的是检查给定的二叉树是否镜像对称,套用递归解题步骤:


1. 找终止条件。树为空的时候递归结束。


2. 找返回值。此题是判断给定的二叉树是否镜像对称,因此返回true或者false。


3. 本级递归应该做什么。给定的函数isSymmetric()的传参只有一个root,而判断二叉树是否镜像,根节点root的左节点left和右节点right的值要相等,而且左节点left的左节点要等于右节点right的右节点,同时左节点left的右节点要等于右节点的左节点(此处的相等为val相等)。另写一个函数,传入左节点left和右节点right,判断是否镜像。

Solution

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean isSymmetric(TreeNode root) {
        if (root == null)
            return true;
        return helper(root.left, root.right);
    }

    public boolean helper(TreeNode left, TreeNode right){
        if (left == null && right == null)
            return true;
        if (left == null || right == null)
            return false;
        if (left.val == right.val)
            return helper(left.left, right.right)
                && helper(left.right, right.left);
        return false;
    }
}

110.平衡二叉树

难度 简单

给定一个二叉树,判断它是否是高度平衡的二叉树。

本题中,一棵高度平衡二叉树定义为:

一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。

示例1:

  给定二叉树 [3,9,20,null,null,15,7]

      3
     / \
    9  20
      /  \
     15   7
  返回 true 

示例2:

  给定二叉树 [1,2,2,3,3,null,null,4,4]

         1
        / \
       2   2
      / \
     3   3
    / \
   4   4
  返回 false 

解题思路

helper返回-1或者是平衡树的高度,即如果是平衡树,则返回值》=0。
helper函数中进行递归:
 1. 边界条件:root == null
 2. 计算左子树的高度
 3. 计算右子树的高度
 4. 判断是否为平衡树
   是:
     返回高度值
   不是:
     返回-1

Solution

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean isBalanced(TreeNode root) {
        return helper(root) >= 0;
    }
    public int helper(TreeNode root){
        if (root == null)
            return 0;
        int leftDepth = helper(root.left);
        int rightDepth = helper(root.right);
        if (leftDepth >=0 && rightDepth >= 0 && Math.abs(leftDepth - rightDepth) <= 1)
            return Math.max(leftDepth, rightDepth) + 1;
        else 
            return -1; 
    }
}

226.翻转二叉树

难度 简单

翻转一棵二叉树。

示例:

  输入:
       4
     /   \
    2     7
   / \   / \
  1   3 6   9

  输出:
       4
     /   \
    7     2
   / \   / \
  9   6 3   1

解题思路:

乍一看,感觉和镜像二叉树十分相似,只是将判断节点值是否相等变成交换值。但是进一步思考后,其实不用这么复杂,每个节点依次递归,在本级递归中只需要将左右节点互换就OK。

Solution

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode invertTree(TreeNode root) {
        if (root == null)
            return null;
        if (root.left == null && root.right == null)
            return root;
        if (root.left != null && root.right == null){
            root.right = root.left;
            root.left = null;
        }else if(root.left == null && root.right != null){
            root.left = root.right;
            root.right = null;
        }else{
            TreeNode temp = root.left;
            root.left = root.right;
            root.right = temp;
        }
        root.left = invertTree(root.left);
        root.right = invertTree(root.right);
        return root;   
    }
}

654.最大二叉树

难度 中等

给定一个不含重复元素的整数数组。一个以此数组构建的最大二叉树定义如下:

二叉树的根是数组中的最大元素。
左子树是通过数组中最大值左边部分构造出的最大二叉树。
右子树是通过数组中最大值右边部分构造出的最大二叉树。
通过给定的数组构建最大二叉树,并且输出这个树的根节点。

示例:

  输入:[3,2,1,6,0,5]
  输出:返回下面这棵树的根节点:
  
        6
      /   \
     3     5
      \    / 
       2  0   
         \
          1

解题思路:

第一次提交的代码超出了内存限制,可能是因为递归传参是数组,每次复制原数组的切片。参考大佬的代码后,其实只需要数组nums,左起始位left和终点位right,递归边界是left > right,观察代码其本质为前序遍历:先完成本级的任务,左节点进行递归,右节点再进行递归,结束返回结果,完成。

Solution

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode constructMaximumBinaryTree(int[] nums) {
        return maxTree(nums, 0, nums.length - 1);
    }
        
    public TreeNode maxTree(int[] nums, int l, int r){
        if (l > r)
            return null;
        int max = findMax(nums, l, r);
        TreeNode root = new TreeNode(nums[max]);
        root.left = maxTree(nums, l, max-1);
        root.right = maxTree(nums, max+1, r);
        return root;
    }

    public int findMax(int[] nums, int l, int r){
        int max = Integer.MIN_VALUE, maxIndex = l;
        for (int i = l; i <= r; i++){
            if (max < nums[i]){
                max = nums[i];
                maxIndex = i;
            }
        }
        return maxIndex;
    }
}

938.二叉搜索树的范围和

难度 简单

给定二叉搜索树的根结点 root,返回 L 和 R(含)之间的所有结点的值的和。

二叉搜索树保证具有唯一的值。

示例1:

  输入:root = [10,5,15,3,7,null,18], L = 7, R = 15
  输出:32

示例2:

  输入:root = [10,5,15,3,7,13,18,1,null,6], L = 6, R = 10
  输出:23

解题思路:

二叉搜索树的特点:左子树所有的值都比节点的值小,而右子树所有的值都比其大。

  1. 递归边界:root == null
  2. 本级任务:先判断节点的值处于哪个范围
      1)小于L:去右子树找
      2)处于寻找范围:进行加法
      3)大于R:去左子树找
  3. 返回值:节点值 + 左边的值 + 右边的值

Solution

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public int rangeSumBST(TreeNode root, int L, int R) {
        if (root == null)
            return 0;
        if (root.val >= L && root.val <= R)
            return root.val + rangeSumBST(root.left, L, R) + rangeSumBST(root.right, L, R);
        else if (root.val < L)
            return rangeSumBST(root.right, L, R);
        else
            return rangeSumBST(root.left, L, R);
        
    }
}

剑指Offer 54.二叉搜索树的第k大节点

难度 简单

给定一棵二叉搜索树,请找出其中第k大的节点。

示例1:

  输入: root = [3,1,4,null,2], k = 1
     3
    / \
   1   4
    \
     2
  输出: 4

示例2:

  输入: root = [5,3,6,2,4,null,null,1], k = 3
         5
        / \
       3   6
      / \
     2   4
    /
   1
  输出: 4  

解题思路:

需要全局变量记录ans和count,本质时中序遍历

  1. 递归边界:++count == k
  2. 本级任务:判断count是否等于k,满足条件直接返回退出。

Solution

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    private int ans = 0, count = 0;

    public int kthLargest(TreeNode root, int k) {
        
        helper(root, k);
        return ans;
    }
    public void helper(TreeNode root, int k){
        if (root.right != null)
            helper(root.right, k);
        if (++count == k){
            ans = root.val;
            return;
        }
        if (root.left != null)
            helper(root.left, k);
    }
}
posted @ 2020-08-20 22:39  Haloya  阅读(125)  评论(0编辑  收藏  举报