二叉树递归解题
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
解题思路:
二叉搜索树的特点:左子树所有的值都比节点的值小,而右子树所有的值都比其大。
- 递归边界:root == null
- 本级任务:先判断节点的值处于哪个范围
1)小于L:去右子树找
2)处于寻找范围:进行加法
3)大于R:去左子树找 - 返回值:节点值 + 左边的值 + 右边的值
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,本质时中序遍历
- 递归边界:++count == k
- 本级任务:判断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);
}
}