1. 把二叉搜索树转换为累加树
给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。
提醒一下,二叉搜索树满足下列约束条件:
- 节点的左子树仅包含键 小于 节点键的节点。
- 节点的右子树仅包含键 大于 节点键的节点。
- 左右子树也必须是二叉搜索树。
示例 1:
输入:[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]
示例 2:
输入:root = [0,null,1]
输出:[1,null,1]
我的解法(无脑递归)
class Solution {
int num = 0;
public TreeNode convertBST(TreeNode root) {
if(root != null){
convertBST(root.right);
root.val += num;
num = root.val;
convertBST(root.left);
return root;
}
return null;
}
}
递归这个东西,我也很迷,只能说多刷了,没准哪天悟了!
2. 岛屿数量
给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围。
示例 1:
输入:grid = [
["1","1","1","1","0"],
["1","1","0","1","0"],
["1","1","0","0","0"],
["0","0","0","0","0"]
]
输出:1
示例 2:
输入:grid = [
["1","1","0","0","0"],
["1","1","0","0","0"],
["0","0","1","0","0"],
["0","0","0","1","1"]
]
输出:3
我的解法(递归)
class Solution {
public int numIslands(char[][] grid) {
// 何为岛屿? 只要(i,j) 水平或竖直方向有陆地(坐标值为1)与坐标(i,j)直接相连
// 这些坐标也属于岛屿的一部分,我们以某个陆地坐标为中心,不断向它四周扩散(递归)、
// 知道所有扩散终止(遇到海洋或者边界),同时扩散过程中遇到的陆地坐标全部标记为 0
// 这样做是为了避免后续遍历重复进行扩散
// 最后统计有几个扩散过程,即为岛屿数量
// 统计岛屿数量
int res = 0;
for(int i = 0; i < grid.length; ++i){
for(int j = 0; j < grid[0].length; ++j){
if(grid[i][j] == '1'){
// grid[i][j] = 1 说明是陆地坐标,开始扩散
dfs(grid, i, j);
// 扩散完成 岛屿数量+1
res++;
}
}
}
return res;
}
public void dfs(char[][] grid, int i, int j){
// 如果遇到海洋坐标 或者 到达边界 停止扩散
// grid[i][j] == '0' 这个放在最后 利用短路特性 否则会出现数组下标越界
if(i < 0 || j < 0 || i >= grid.length || j >= grid[0].length || grid[i][j] == '0') return;
// 将散过程中遇到的陆地坐标全部标记为 0,避免后续遍历重复进行扩散
grid[i][j] = '0';
// 向四周扩散
dfs(grid, i - 1, j);
dfs(grid, i + 1, j);
dfs(grid, i, j + 1);
dfs(grid, i, j - 1);
}
}
今天想和大家说点心里话,我刷算法题有一段时间了,但是说实话一直还处于在算法大门外面徘徊的样子。做题时很少能够立刻看出思路,其实这道题我之前也刷到过类似的,但是今天做,其实还是很懵逼,甚至于一开始连题都读不懂,如果是以前的话,我可能会绝望,但是现在,被打击习惯了,脸皮也就厚一点了,实在不懂,就看看题解,然后自己去理解,再自己写出来。但我总觉得自己在算法这条路上很难,或者说是天赋有限,当然可能也是没有那么多时间去刷题,去总结。
我说这些不是劝退大家,更不是宣泄自己的负能量,这是不可能的,这不是我写博客的初衷,我只是想和大家说一说,可能很多人都会遇到我这种情况,也处在迷茫中。
希望你看到这里,能够缓解一下自己的情绪,至少,这种迷茫无力感觉不是只有你一个人有,至少,我现在还是这样。一起加油吧,我也期待将来我也能够从容地面对算法,面对我的不足,感谢大家听我废话。
3. 每日温度
给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer ,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用 0 来代替。
示例 1:
输入: temperatures = [73,74,75,71,69,72,76,73]
输出: [1,1,4,2,1,1,0,0]
示例 2:
输入: temperatures = [30,40,50,60]
输出: [1,1,1,0]
示例 3:
输入: temperatures = [30,60,90]
输出: [1,1,0]
我的解法(暴力破解,会超时)
class Solution {
public int[] dailyTemperatures(int[] temperatures) {
int[] res = new int[temperatures.length];
for(int i = 0; i < temperatures.length - 1; ++i){
for(int j = i + 1; j < temperatures.length; ++j){
if(temperatures[j] > temperatures[i]){
res[i] = j - i;
break;
}
}
}
return res;
}
}
我的解法(动态规划)
class Solution {
public int[] dailyTemperatures(int[] temperatures) {
/**
* 这道题我们可以试着倒着推导 最后一天后面显然不会有比它还高的,所以直接为0
* 再看倒数第二天,如果最后一天的气温比他高,那就结果为 1,否则为 0
* 到这里,我们可以这样假设,是不是我们想要知道第 i 天的结果,只需要知道第 i+1 天的结果
* 如果T[i] < T[i+1] 那么 res[i] = 1
* 如果T[i] > T[i+1]
* 如果 res[i+1] = 0,那么显然 T[i] = 0
* 如果 res[i+1] != 0 那就比较 T[i] 和 T[i+1+res[i+1]]
*/
int len = temperatures.length;
int[] res = new int[len];
for(int i = len - 2; i >= 0; i--){
for(int j = i + 1; j < len; j += res[j]){
if(temperatures[i] < temperatures[j]){
res[i] = j - i;
break;
}else if(res[j] == 0){
res[i] = 0;
break;
}
}
}
return res;
}
}