二叉樹遞迴解題
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);
}
}