一、 数组类型解题方法一:二分法
二、数组类型解题方法二:双指针法
三、数组类型解题方法三:滑动窗口
四、数组类型解题方法四:模拟
五、链表篇之链表的基础操作和经典题目
六、哈希表篇之经典题目
七、字符串篇之经典题目
八、字符串篇之 KMP
九、解题方法:双指针
十、栈与队列篇之经典题目
十 一、栈与队列篇之 top-K 问题
十 二、二叉树篇之二叉树的前中后序遍历
十 三、二叉树篇之二叉树的层序遍历及相关题目
十 四、二叉树篇之二叉树的属性相关题目
十 五、 二叉树篇之二叉树的修改与构造
十 六、 二叉树篇之二叉搜索树的属性
十 七、二叉树篇之公共祖先问题
更新中 … …
刷题路线来自 :代码随想录
Leetcode 链接
给定二叉搜索树(BST)的根节点 root 和要插入树中的值 value ,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同。注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回 任意有效的结果 。
示例 1:
输入:root = [4,2,7,1,3], val = 5
输出:[4,2,7,1,3,5]
解释:另一个满足题目要求可以通过的树是:
示例 2:
输入:root = [40,20,60,10,30,50,70], val = 25
输出:[40,20,60,10,30,50,70,null,null,25]
示例 3:
输入:root = [4,2,7,1,3,null,null,null,null,null,null], val = 5
输出:[4,2,7,1,3,5]
题解:
按照二叉搜索树的规则去遍历,遇到空节点就插入节点就可以了
方式一:递归
利用返回值完成新加入的节点与其父节点的赋值操作,
class Solution {
public TreeNode insertIntoBST(TreeNode root, int val) {
if (root == null) return new TreeNode(val);
// 本层用root->left或者root->right将其接住下一层返回的结点
// 下层返回结点的可能:
// 1.向下递归时遇见空结点,即可返回构造好的 val 结点
// 2.向上回溯时返回
if (val < root.val) root.left = insertIntoBST(root.left, val);
if (val > root.val) root.right = insertIntoBST(root.right, val);
return root;
}
}
方式二:迭代法
遍历到 null 时加入新节点,需要知道父亲结点,所以使用一个结点保存父亲结点
class Solution {
public TreeNode insertIntoBST(TreeNode root, int val) {
if (root == null) return new TreeNode(val);
TreeNode cur = root;
TreeNode pre = root;
while (cur != null) {
// 保存父亲结点
pre = cur;
// 寻找插入位置
if (val > cur.val) {
cur = cur.right;
} else if (val < cur.val) {
cur = cur.left;
}
}
// 此时不知道插入位置是父亲结点的左还是右,需要判断一下
if (val < pre.val) {
pre.left = new TreeNode(val);
} else {
pre.right = new TreeNode(val);
}
return root;
}
}
Leetcode 链接
给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。
一般来说,删除节点可分为两个步骤:
首先找到需要删除的节点;
如果找到了,删除它。
输入:root = [5,3,6,2,4,null,7], key = 3
输出:[5,4,6,2,null,null,7]
解释:给定需要删除的节点值是 3,所以我们首先找到 3 这个节点,然后删除它。
一个正确的答案是 [5,4,6,2,null,null,7], 如下图所示。
另一个正确答案是 [5,2,6,null,4,null,7]。
示例 2:
输入: root = [5,3,6,2,4,null,7], key = 0
输出: [5,3,6,2,4,null,7]
解释: 二叉树不包含值为 0 的节点
示例 3:
输入: root = [], key = 0
输出: []
题解:
class Solution {
public TreeNode deleteNode(TreeNode root, int key) {
if (root == null) return root;
if (key < root.val) {
root.left = deleteNode(root.left, key);
} else if (key > root.val) {
root.right = deleteNode(root.right, key);
} else {
// 找到删除的结点了
TreeNode left = root.left;
// 右结点空,返回左结点 左结点,返回右结点
if (root.right == null) {
return root.left;
} else if (root.left == null) {
return root.right;
} else {
// 左右都不为空,将左子树放到右子树的适当位置上
TreeNode cur = root.right;
// 找到右子树的最左边
while (cur.left != null) {
cur = cur.left;
}
cur.left = left;
return root.right;
}
}
return root;
}
}
Leetcode 链接
给你二叉搜索树的根节点 root ,同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树,使得所有节点的值在[low, high]中。修剪树 不应该 改变保留在树中的元素的相对结构 (即,如果没有被移除,原有的父代子代关系都应当保留)。 可以证明,存在 唯一的答案 。所以结果应当返回修剪好的二叉搜索树的新的根节点。注意,根节点可能会根据给定的边界发生改变。
示例 1:
输入:root = [1,0,2], low = 1, high = 2
输出:[1,null,2]
示例 2:
输入:root = [3,0,4,null,2,null,null,1], low = 1, high = 3
输出:[3,2,null,1]
题解:
错误解:直接 root == null || root.val < low || root.val > high 就 return null,0 虽然小于 1 但是不能直接将左子树全部移除
class Solution {
public TreeNode trimBST(TreeNode root, int low, int high) {
if (root == null || root.val < low || root.val > high) return null;
root.left = trimBST(root.left, low, high);
root.right = trimBST(root.right, low, high);
return root;
}
}
方式一:递归法
class Solution {
public TreeNode trimBST(TreeNode root, int low, int high) {
if (root == null) return root;
if (root.val < low) {
// 0 小于 1,跳过左子树,直接去递归大于 0 的右子树,返回的适合相当于跳过了这一层结点
return trimBST(root.right, low, high);
}
if (root.val > high) {
return trimBST(root.left, low, high);
}
root.left = trimBST(root.left, low, high);
root.right = trimBST(root.right, low, high);
return root;
}
}
方式二:迭代法
class Solution {
public TreeNode trimBST(TreeNode root, int low, int high) {
if (root == null) return root;
// 处理头结点,让root移动到[L, R] 范围内,注意是左闭右闭
while (root != null && (root.val < low || root.val > high)) {
if (root.val < low) {
root = root.right;
} else {
root = root.left;
}
}
// 此时root已经在[L, R] 范围内,处理左孩子元素小于L的情况
TreeNode cur = root;
while (cur != null) {
// 同示例二
while (cur.left != null && cur.left.val < low) {
cur.left = cur.left.right;
}
cur = cur.left;
}
// 此时root已经在[L, R] 范围内,处理右孩子大于R的情况
cur = root;
while (cur != null) {
while (cur.right != null && cur.right.val > high) {
cur.right = cur.right.left;
}
cur = cur.right;
}
return root;
}
}
Leetcode 链接
给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。
示例 1:
输入:nums = [-10,-3,0,5,9]
输出:[0,-3,9,-10,null,5]
解释:[0,-10,5,null,-3,null,9] 也将被视为正确答案:
示例 2:
输入:nums = [1,3]
输出:[3,1]
解释:[1,3] 和 [3,1] 都是高度平衡二叉搜索树。
题解:
回顾 二叉树篇之二叉树的修改与构造
class Solution {
public TreeNode sortedArrayToBST(int[] nums) {
return build(nums, 0, nums.length);
}
public TreeNode build(int[] nums, int left, int right) {
// 区间内没有结点
if (right - left <= 0) {
return null;
}
// 区间内只剩一个结点
if (right - left == 1) {
return new TreeNode(nums[left]);
}
// 每次将中间结点作为根节点
int mid = left + (right - left) / 2;
TreeNode root = new TreeNode(nums[mid]);
root.left = build(nums, left, mid);
root.right = build(nums, mid + 1, right);
return root;
}
}
Leetcode 链接
给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。
提醒一下,二叉搜索树满足下列约束条件:
节点的左子树仅包含键 小于 节点键的节点。
节点的右子树仅包含键 大于 节点键的节点。
左右子树也必须是二叉搜索树。
输入:[4,1,6,0,2,5,7,null,null,null,3,null,null,null,8]
输出:[30,36,21,36,35,26,15,null,null,null,33,null,null,null,8]
题解:
中序遍历
class Solution {
public TreeNode convertBST(TreeNode root) {
dfs(root);
return root;
}
int sum = 0;
public void dfs(TreeNode root) {
if (root == null) return;
// 左
dfs(root.right);
// 中
sum += root.val;
root.val = sum;
// 右
dfs(root.left);
}
}