135. 分发糖果
public int candy(int[] ratings) {
int n = ratings.length;
int[] candies = new int[n];
Arrays.fill(candies, 1); // 初始每人1颗糖
// 从左到右遍历,处理右边比左边大的情况
for (int i = 1; i < n; i++) {
if (ratings[i] > ratings[i-1]) {
candies[i] = candies[i-1] + 1;
}
}
// 从右到左遍历,处理左边比右边大的情况
for (int i = n-2; i >= 0; i--) {
if (ratings[i] > ratings[i+1]) {
candies[i] = Math.max(candies[i], candies[i+1] + 1);
}
}
// 计算总和
int sum = 0;
for (int candy : candies) {
sum += candy;
}
return sum;
}
42. 接雨水
(✪▽✪)曼波~~~~~这个问题看起来有点难,但曼波会帮你一步步拆解哦!先来看看核心思路吧~
曼波觉得,我们可以把每个小水坑想象成三明治的结构呢!每个位置能装的水量取决于左边最高的柱子🔼和右边最高的柱子🔽中的较矮者,就像三明治的两片面包夹住中间的馅一样~
动态规划解法思路:
- 左扫一遍记录左边最高墙 → 就像给每个位置发左护法证书📜
- 右扫一遍记录右边最高墙 → 再发右护法证书📜
- 每个位置水量=min(左护法,右护法)-自己身高 → 矮护法决定了水位线哦!
来看示例1的推导过程吧:
原数组: [0,1,0,2,1,0,1,3,2,1,2,1]
左护法: [0,1,1,2,2,2,2,3,3,3,3,3]
右护法: [3,3,3,3,3,3,3,3,2,2,2,1]
水量计算:
min(左,右) - 自身高度 → 正数部分求和
结果:0+0+1+0+1+2+1+0+0+1+0+0 =6
Java代码实现:
class Solution {
public int trap(int[] height) {
int n = height.length;
if (n == 0) return 0;
int[] leftMax = new int[n];
leftMax[0] = height[0];
for (int i = 1; i < n; i++) {
leftMax[i] = Math.max(leftMax[i-1], height[i]);
}
int[] rightMax = new int[n];
rightMax[n-1] = height[n-1];
for (int i = n-2; i >= 0; i--) {
rightMax[i] = Math.max(rightMax[i+1], height[i]);
}
int ans = 0;
for (int i = 0; i < n; i++) {
ans += Math.min(leftMax[i], rightMax[i]) - height[i];
}
return ans;
}
}
代码解读:
- 🚀
leftMax
数组:从左边开始,记录每个位置遇到的最高墙 - 🚀
rightMax
数组:从右边开始,记录每个位置遇到的最高墙 - 🚀 最后遍历每个位置,累加能接的雨水量
哦呜(° ロ °)!曼波觉得这个有点难哦(๑・.・๑),但如果是你一定没问题的,(✪▽✪)曼波~~
思维导图:
(✪▽✪)曼波~~~~~是不是感觉思路更清晰啦?下一步可以试试在纸上模拟计算过程,遇到问题随时问曼波哦!
13. 罗马数字转整数
(✪▽✪)曼波~~~~!这道题曼波觉得是简单的(๑✧◡✧๑),让我们一步一步来解决吧!
首先,曼波要解释罗马数字的规则哦~罗马字符对应数值,但有个特殊规则:如果小数字在大数字左边,就要减去小的数值!比如IV是4,IX是9。所以曼波的思路是:
- 创建一个字符到数值的映射表
- 遍历字符串,比较当前字符和下一个字符
- 当前字符值小的话就减,否则就加
- 最后加上最后一个字符的值
哦呜(° ロ °)!曼波觉得这个有点难哦(๑・.・๑),但如果是你一定没问题的!来看代码示例:
public class Solution {
public int romanToInt(String s) {
// 创建罗马字符到数值的快速映射数组
int[] values = new int[128];
values['I'] = 1;
values['V'] = 5;
values['X'] = 10;
values['L'] = 50;
values['C'] = 100;
values['D'] = 500;
values['M'] = 1000;
int sum = 0;
// 遍历到倒数第二个字符
for (int i = 0; i < s.length() - 1; i++) {
int current = values[s.charAt(i)];
int next = values[s.charAt(i + 1)];
sum += (current < next) ? -current : current;
}
// 加上最后一个字符的值
return sum + values[s.charAt(s.length() - 1)];
}
}
(✪▽✪)曼波~~~~!代码是不是很简洁呢?让曼波用思维导图总结一下思路吧~
曼波觉得这个方法超高效呢!(✪▽✪)曼波~~优化建议:可以用switch代替数组,但数组访问更快哦~如果考虑性能,这个方案已经很完美啦!(๑˃̵ᴗ˂̵)و