本周的力扣周结我并没有刷很多的题,回溯模块最近才开始刷,先把树巩固好
解题思路
利用二叉搜索树的性质去寻找指定值的结点(假设树中结点没有重复元素),二叉搜索树中根节点的左孩子一定小于其根节点,根节点的右孩子一定大于其根节点,因为我们需要返回指定的子树所以,我们递归函数的返回值不为空
核心代码
class Solution {
public TreeNode searchBST(TreeNode root, int val) {
if(root == null || root.val == val){
return root;
}
TreeNode node = null;
if(root.val > val){
node = searchBST(root.left, val);
}
if(root.val < val){
node = searchBST(root.right, val);
}
return node;
}
}
时间复杂度
O(n)
空间复杂度
O(n)
解题思路
中序遍历二叉搜索树,要遍历每一个结点判断每一个结点都是否符合二叉搜索树的性质。
核心代码
class Solution {
TreeNode max;
public boolean isValidBST(TreeNode root) {
if(root == null) {
return true;
}
if(!isValidBST(root.left)) {
return false;
}
if(max != null && root.val <= max.val) {
return false;
}
max = root;
return isValidBST(root.right);
}
}
时间复杂度
O(n)
空间复杂度
O(n)
解题思路
这道题和上一题的思路大概一致,要中序遍历每个二叉搜索树的结点,并且要记录父结点,用于上一层的调用
核心代码
class Solution {
TreeNode node;
int min = Integer.MAX_VALUE;
public int getMinimumDifference(TreeNode root) {
inorder(root);
return min;
}
public void inorder(TreeNode root) {
if(root == null) {
return;
}
inorder(root.left);
if(node != null && root.val - node.val < min) {
min = root.val - node.val;
}
node = root;
inorder(root.right);
}
}
时间复杂度
O(n)
空间复杂度
O(n)
解题思路
这道题力扣虽然表为easy是因为可以使用暴力破解,如果使用纯递归的的话,还是比较难的,还是利用二叉搜索树的性质,中序遍历相当于从小到大遍历,使用一个ThreeNode类型来记录前驱结点,使用一个额外的空间来记录出现的次数,如果当前结点和前驱结点不等就重新记录
核心代码
class Solution {
int max = 1;
int temp = 1;
TreeNode node;
ArrayList<Integer> mode = new ArrayList<>();
public int[] findMode(TreeNode root) {
inorder(root);
int[] result = new int[mode.size()];
for(int i = 0; i < result.length; i++) {
result[i] = mode.get(i);
}
return result;
}
public void inorder(TreeNode root) {
if(root == null) {
return;
}
inorder(root.left);
if(node == null || root.val != node.val) {
temp = 1;
} else {
temp++;
}
if(temp > max) {
mode.clear();
mode.add(root.val);
max = temp;
} else if (temp == max) {
mode.add(root.val);
}
node = root;
inorder(root.right);
}
}
时间复杂度
O(n)
空间复杂度
O(n)
解题思路
寻找最近的公共祖先,如果发现一个结点,它的左子树和右子树分别包括左右结点那么就找到了公共祖先,所以我们可以后序遍历二叉树
核心代码
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == p || root == q || root == null) {
return root;
}
TreeNode left = lowestCommonAncestor(root.left, p, q);
TreeNode right = lowestCommonAncestor(root.right, p, q);
if(left != null && right != null) {
return root;
}
if(left == null) {
return right;
}
return left;
}
}
时间复杂度
O(n)
空间复杂度
O(n)
解题思路
区别于上一道题,这道题的搜索可以依赖于二叉树的性质,如果要寻找的结点的值都大于根结点那么就寻找他的右子树,如果寻找的结点的值都小于根节点那么就寻找左子树,如果都不是就证明寻找的值分布在跟结点的两侧,直接返回根节点即可。
核心代码
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(p.val > root.val && q.val > root.val) {
return lowestCommonAncestor(root.right, p, q);
} else if (p.val < root.val && q.val < root.val) {
return lowestCommonAncestor(root.left, p, q);
}
return root;
}
}
时间复杂度
O(n)
空间复杂度
O(n)
解题思路
二叉搜索树的插入是不需要破坏原有树的结构的,所以我们直接利用二叉搜索树的性质即可完成插入
核心代码
class Solution {
public TreeNode insertIntoBST(TreeNode root, int val) {
if(root == null) {
root = new TreeNode(val);
return root;
}
if(root.val > val) {
root.left = insertIntoBST(root.left, val);
} else if (root.val < val) {
root.right = insertIntoBST(root.right, val);
}
return root;
}
}
时间复杂度
O(n)
空间复杂度
O(n)
解题思路
删除二叉树的结点,情况涉及的就比较多了,这五种情况必须全部考虑到
- 如果删除的是叶子结点,那么直接删除就好了
- 如果删除的结点右孩子不为空,那么删除结点返回右孩子就好了
- 如果删除的结点左孩子不为空但是右孩子为空,那么直接删除结点返回左孩子就好了
- 如果删除的结点左右孩子都不为空,那么就将左孩子的根节点连接到,右孩子最左子树的根节点上
- 如果就找不到删除结点,直接返回根节点即可
这道题不需要遍历所有的结点,只需要删除待删除的结点返回最终结果即可
核心代码
class Solution {
public TreeNode deleteNode(TreeNode root, int key) {
if(root == null) {
return root;
}
if(root.val == key) {
if(root.left == null && root.right == null) {
return null;
}else if (root.left != null && root.right == null) {
root = root.left;
return root;
}else if (root.left == null && root.right != null) {
root = root.right;
return root;
}else if (root.left != null && root.right != null) {
TreeNode temp = root.right;
while(temp.left != null) {
temp = temp.left;
}
temp.left = root.left;
root = root.right;
return root;
}
}
if(key < root.val) {
root.left = deleteNode(root.left, key);
}else {
root.right = deleteNode(root.right, key);
}
return root;
}
}
时间复杂度
O(n)
空间复杂度
O(n)
解题思路
这道题和450基本类似,好多题都能看到卡哥的用心良苦,这套力扣刷题攻略我已经走了大半学到了很多东西,从刚开始的恐惧算法到现在每天不刷两三个小时浑身不自在,感谢卡哥
核心代码
class Solution {
public TreeNode trimBST(TreeNode root, int low, int high) {
if(root == null) {
return root;
}
root.left = trimBST(root.left, low, high);
root.right = trimBST(root.right, low, high);
if(root.val < low || root.val > high) {
if(root.left == null && root.right == null) {
root = null;
return root;
}else if (root.left != null && root.right == null) {
root = root.left;
return root;
}else if (root.left == null && root.right != null) {
root = root.right;
return root;
}else {
TreeNode temp = root.right;
while(temp.left != null) {
temp = temp.left;
}
temp.left = root.left;
root = root.right;
return root;
}
}
return root;
}
}
时间复杂度
O(n)
空间复杂度
O(n)
解题思路
注意越界条件
核心代码
class Solution {
public TreeNode sortedArrayToBST(int[] nums) {
return build(nums, 0, nums.length - 1);
}
public TreeNode build(int[] nums, int left, int right) {
if (left > right) {
return null;
}
int mid = left + (right - left) / 2;
TreeNode root = new TreeNode(nums[mid]);
root.left = build(nums, left, mid - 1);
root.right = build(nums, mid + 1, right);
return root;
}
}
时间复杂度
O(n)
空间复杂度
O(logn)
解题思路
这道题的难点应该是在于对题目的理解吧
核心代码
class Solution {
int sum = 0;
public TreeNode convertBST(TreeNode root) {
if(root == null) {
return null;
}
convertBST(root.right);
sum += root.val;
root.val = sum;
convertBST(root.left);
return root;
}
}
时间复杂度
O(n)
空间复杂度
O(n)
|