今天的力扣记录是代码随想录的二叉搜索树修改、删减等题目和双指针的反转单词、调整数组顺序等题目。二叉搜索树确实很有规律,如果是中序,就可以直接从小到大有序排列,所以可以直接走中序,记录好前一个节点或者前一个节点数值。
235. 二叉搜索树的最近公共祖先
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q)从这个可以看到,在p和q里找公共祖先,那肯定是判断根节点和pq之间的相对大小,如果都在左侧,那么直接递归到左子树去判断;同理,都在右侧,直接去右子树判断,那么一左一右就肯定找到了,根节点就是最近公共祖先。
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == p || root == q || root == null) return root;
//二叉搜索树有个神奇的特性
//都在左,递归左边,都在右,递归右边
//一左一右,返回中间
if(root.val > p.val && root.val > q.val){
TreeNode left = lowestCommonAncestor(root.left, p, q);
if(left != null) return left;
}
if(root.val < q.val && root.val < p.val){
TreeNode right = lowestCommonAncestor(root.right, p, q);
if(right != null) return right;
}
return root;
}
}
701.二叉搜索树中的插入操作
这个二叉搜索树的插入,那直接走到左子树或者右子树的叶子节点,那凑左边或者右边就行。这个肯定是递归操作,如果大于就走左边去递归,但是要用root去接着;如果小于就是右边递归,用root接着;关键是中间的跟节点肯定是插入操作,看到空再操做。
class Solution {
public TreeNode insertIntoBST(TreeNode root, int val) {
if(root == null){
TreeNode tmp = new TreeNode(val);
return tmp;
}
//遍历
if(root.val > val){
root.left = insertIntoBST(root.left, val);
}
if(root.val < val){
root.right = insertIntoBST(root.right, val);
}
return root;
}
}
450.删除二叉搜索树中的节点
删除那肯定也是要判断,如果value对上了,就是可以判断如何删除;不对,就是左右递归。删除的逻辑就是如果都空了,返回就行,如果是左右有一个为空,返回另一个就行,两个都不为空,那不能简单凑在一起,需要左右子树的一支走到空,然后把另一只放到尾上,返回适合的节点。
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;
}
if(root.left == null){
return root.right;
}
if(root.right == null){
return root.left;
}
if(root.left != null && root.right != null){
// root.left = root.right.left;
//正儿八经的右节点走到底,
//得把右子树的左节点走到空,总会有空的
TreeNode tmp = root.right;
while(tmp.left != null){
tmp = tmp.left;
}
tmp.left = root.left;
return root.right;
}
}
if(root.val > key){
root.left = deleteNode(root.left, key);
}
if(root.val < key){
root.right = deleteNode(root.right, key);
}
return root;
}
}
669. 修剪二叉搜索树
这个是在low和high的节点都保存下来,这个肯定是先序就可以操作,关键是中节点是怎么操作,如果是中节点大于high,那么递归左子树(右子树没了);反过来依然,然后中节点搞完,可以递归左右节点,直接接住就行。
class Solution {
public TreeNode trimBST(TreeNode root, int low, int high) {
if(root == null) return null;
if(root.val > high || root.val < low){
//去除的逻辑
if(root.val > high){
//条件一:左右都空
if(root.left == null) return null;
if(root.left != null){
return trimBST(root.left, low, high);
}
}
if(root.val < low){
if(root.right == null) return null;
if(root.right != null){
return trimBST(root.right, low, high);
}
}
}
root.left = trimBST(root.left, low, high);
root.right = trimBST(root.right, low, high);
return root;
}
}
538.把二叉搜索树转换为累加树
这个肯定就是反过来右中左这个反中序就行,关键是要保存前面的值,这个采用全局变量就行。
class Solution {
int pre = 0;
public TreeNode convertBST(TreeNode root) {
if(root == null) return root;
TreeNode right = convertBST(root.right);
root.val += pre;
pre = root.val;
TreeNode left = convertBST(root.left);
return root;
}
}
剑指 Offer 58 - I. 翻转单词顺序
这个感觉不像中等题目,但是思路是很明确的,直接搞,先去中间的和左右多余的空格,接着反转。
class Solution {
public String reverseWords(String s) {
StringBuilder sb = trimSpaces(s);
// 翻转字符串
reverse(sb, 0, sb.length() - 1);
// 翻转每个单词
reverseEachWord(sb);
return sb.toString();
}
public StringBuilder trimSpaces(String s) {
int left = 0, right = s.length() - 1;
// 去掉字符串开头的空白字符
while (left <= right && s.charAt(left) == ' ') {
++left;
}
// 去掉字符串末尾的空白字符
while (left <= right && s.charAt(right) == ' ') {
--right;
}
// 将字符串间多余的空白字符去除
StringBuilder sb = new StringBuilder();
while (left <= right) {
char c = s.charAt(left);
if (c != ' ') {
sb.append(c);
} else if (sb.charAt(sb.length() - 1) != ' ') {
sb.append(c);
}
++left;
}
return sb;
}
public void reverse(StringBuilder sb, int left, int right) {
while (left < right) {
char tmp = sb.charAt(left);
sb.setCharAt(left++, sb.charAt(right));
sb.setCharAt(right--, tmp);
}
}
public void reverseEachWord(StringBuilder sb) {
int n = sb.length();
int start = 0, end = 0;
while (start < n) {
// 循环至单词的末尾
while (end < n && sb.charAt(end) != ' ') {
++end;
}
// 翻转单词
reverse(sb, start, end - 1);
// 更新start,去找下一个单词
start = end + 1;
++end;
}
}
}