- 左右子树也必须是二叉搜索树。
示例:
输入:root = [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]
提示:
-
树中的节点数介于
0
和104
之间。 -
每个节点的值介于
-104
和104
之间。 -
树中的所有值 互不相同 。
-
给定的树为二叉搜索树。
思路:
遍历顺序:右 - 中 - 左 ,
ans
记录当前遍历过的节点和,记得更新root->val
class Solution {
public:
TreeNode* convertBST(TreeNode* root) {
int ans = 0;
dfs(root, ans);
return root;
}
//右 - 中 - 左 遍历, ans记录和
void dfs(TreeNode* root, int& ans) {
if(root == nullptr) return ;
dfs(root->right, ans);
root->val += ans;
ans = root->val;
dfs(root->left, ans);
}
};
=============================================================================
题目:
实现一个二叉搜索树迭代器类
BSTIterator
,表示一个按中序遍历二叉搜索树(BST
)的迭代器:
BSTIterator(TreeNode root)
初始化BSTIterator
类的一个对象。BST
的根节点root
会作为构造函数的一部分给出。指针应初始化为一个不存在于BST
中的数字,且该数字小于 BST 中的任何元素。
boolean hasNext()
如果向指针右侧遍历存在数字,则返回true
;否则返回false
。
- int next()将指针向右移动,然后返回指针处的数字。
注意,指针初始化为一个不存在于 `BST` 中的数字,所以对 `next()` 的首次调用将返回 `BST` 中的最小元素。
可以假设 next() 调用总是有效的,也就是说,当调用 next() 时,BST 的中序遍历中至少存在一个下一个数字。
示例:
输入
inputs = [“BSTIterator”, “next”, “next”, “hasNext”, “next”, “hasNext”, “next”, “hasNext”, “next”, “hasNext”]
inputs = [[[7, 3, 15, null, null, 9, 20]], [], [], [], [], [], [], [], [], []]
输出
[null, 3, 7, true, 9, true, 15, true, 20, false]
解释
BSTIterator bSTIterator = new BSTIterator([7, 3, 15, null, null, 9, 20]);
bSTIterator.next(); // 返回 3
bSTIterator.next(); // 返回 7
bSTIterator.hasNext(); // 返回 True
bSTIterator.next(); // 返回 9
bSTIterator.hasNext(); // 返回 True
bSTIterator.next(); // 返回 15
bSTIterator.hasNext(); // 返回 True
bSTIterator.next(); // 返回 20
bSTIterator.hasNext(); // 返回 False
提示:
-
树中节点的数目在范围
[1, 105]
内 -
0 <= Node.val <= 106
-
最多调用
105
次hasNext
和next
操作
思路:
将二叉搜索树中序遍历并存储到数组中,通过数组实现
next()
,hasNext()
就简单多了
class BSTIterator {
private:
vector arr;
int index = 0;
//中序遍历并存储到数组中
void dfs(TreeNode* root) {
if(!root) return ;
dfs(root->left);
arr.push_back(root->val);
dfs(root->right);
}
public:
BSTIterator(TreeNode* root) {
dfs(root);
}
int next() {
return arr[index++];
}
bool hasNext() {
if(index < arr.size())
return true;
else
return false;
}
};
=================================================================================
题目:
给定一个二叉搜索树的 根节点 root 和一个整数 k , 请判断该二叉搜索树中是否存在两个节点它们的值之和等于 k 。假设二叉搜索树中节点的值均唯一。
示例:
输入: root = [8,6,10,5,7,9,11], k = 12
输出: true
解释: 节点 5 和节点 7 之和等于 12
提示:
-
二叉树的节点个数的范围是
[1, 104].
-
-104 <= Node.val <= 104
-
root
为二叉搜索树 -
-105 <= k <= 105
思路:
将遍历过的值存储在
map
中,通过map[k - root->val]
去map
中寻找答案
class Solution {
public:
bool ok = false;
unordered_map<int, int> map;
bool findTarget(TreeNode* root, int k) {
dfs(root, k);
return ok;
}
void dfs(TreeNode* root, int k) {
if(root == nullptr || ok) return ;
if(map[k - root->val]) {
ok = true;
return ;
}
map[root->val]++;
dfs(root->left, k);
dfs(root->right, k);
}
};
===================================================================================
题目:
给你一个整数数组
nums
和两个整数k
和t
。请你判断是否存在 两个不同下标i
和j
,使得abs(nums[i] - nums[j]) <= t
,同时又满足abs(i - j) <= k 。
如果存在则返回 true,不存在返回 false。
示例:
输入:nums = [1,2,3,1], k = 3, t = 0
输出:true
提示:
-
0 <= nums.length <= 2 * 104
-
-231 <= nums[i] <= 231 - 1
-
0 <= k <= 104
-
0 <= t <= 231 - 1
思路:
用滑动窗窗口来约束一定在 k 内
abs(a - b) <= t
情况下, b肯定在[a-t, b+t] (t>0)
区间内
所以求出上限,下限,然后通过
lower_bound()
求出大于等于下限的数,再判断是否小于等于上限即可
class Solution {
public:
bool containsNearbyAlmostDuplicate(vector& nums, int k, int t) {
set set;
for (int i = 0; i < nums.size(); ++i) {
//下限
long lowerLimit = (long)nums[i] - t;
//上限
long upperLimit = (long)nums[i] + t;
//查找大于等于下限的数
auto it = set.lower_bound(lowerLimit);
if (it != set.end() && *it <= upperLimit) {
return true;
}
set.insert(nums[i]);
//滑动窗口
if (i >= k) {
set.erase(nums[i - k]);
}
}
return false;
}
};
========================================================================
题目:
请实现一个 MyCalendar 类来存放你的日程安排。如果要添加的时间内没有其他安排,则可以存储这个新的日程安排。
MyCalendar 有一个 book(int start, int end)方法。它意味着在 start 到 end 时间内增加一个日程安排,注意,这里的时间是半开区间,即 [start, end), 实数 x 的范围为, start <= x < end。
当两个日程安排有一些时间上的交叉时(例如两个日程安排都在同一时间内),就会产生重复预订。
每次调用 MyCalendar.book方法时,如果可以将日程安排成功添加到日历中而不会导致重复预订,返回 true。否则,返回 false 并且不要将该日程安排添加到日历中。
请按照以下步骤调用 MyCalendar 类: MyCalendar cal = new MyCalendar(); MyCalendar.book(start, end)
示例:
输入:
[“MyCalendar”,“book”,“book”,“book”]
[[],[10,20],[15,25],[20,30]]
输出: [null,true,false,true]
解释:
MyCalendar myCalendar = new MyCalendar();
MyCalendar.book(10, 20); // returns true
MyCalendar.book(15, 25); // returns false ,第二个日程安排不能添加到日历中,因为时间 15 已经被第一个日程安排预定了
MyCalendar.book(20, 30); // returns true ,第三个日程安排可以添加到日历中,因为第一个日程安排并不包含时间 20
提示:
-
每个测试用例,调用
MyCalendar.book
函数最多不超过1000
次。 -
0 <= start < end <= 109
思路:
题目一堆废话,就是要判断区间是否交叉
要判断当前区间是否能够存入
map
,满足一下两个条件就可以
- 用
lower_bound()
求出大于等于start
的数,这个数的start
要大于 插入数 的end
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。**
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-BwDEB5bz-1715795862743)]
[外链图片转存中…(img-Uc8hNPUp-1715795862743)]
[外链图片转存中…(img-avplofe1-1715795862744)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!