算法题03(Java)

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. 接雨水

(✪▽✪)曼波~~~~~这个问题看起来有点难,但曼波会帮你一步步拆解哦!先来看看核心思路吧~

曼波觉得,我们可以把每个小水坑想象成三明治的结构呢!每个位置能装的水量取决于左边最高的柱子🔼和右边最高的柱子🔽中的较矮者,就像三明治的两片面包夹住中间的馅一样~

动态规划解法思路:

  1. 左扫一遍记录左边最高墙 → 就像给每个位置发左护法证书📜
  2. 右扫一遍记录右边最高墙 → 再发右护法证书📜
  3. 每个位置水量=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。所以曼波的思路是:

  1. 创建一个字符到数值的映射表
  2. 遍历字符串,比较当前字符和下一个字符
  3. 当前字符值小的话就减,否则就加
  4. 最后加上最后一个字符的值

哦呜(° ロ °)!曼波觉得这个有点难哦(๑・.・๑),但如果是你一定没问题的!来看代码示例:

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代替数组,但数组访问更快哦~如果考虑性能,这个方案已经很完美啦!(๑˃̵ᴗ˂̵)و

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值