
两篇题目,按题号顺序,格式:题目链接 → 题目分析 → 算法原理 → 代码编写,最后整体总结
题目 1:LeetCode 495. 提莫攻击
题目分析
提莫持续向敌人发射毒素攻击,timeSeries 数组记录每次攻击的时间点,每次中毒持续 duration 秒。 如果下一次攻击到来时,敌人还处在中毒状态,那么中毒时间会被刷新,不会叠加。求敌人总共中毒的总时长。 暴力思路逐个区间判断即可,属于经典模拟题。
算法原理
遍历每两次相邻攻击时间 timeSeries[i] 和 timeSeries[i-1]:
- 两次攻击间隔
diff = timeSeries[i] - timeSeries[i-1] - 如果
diff < duration:说明毒素还没结束就被重置,这一段有效中毒时间就是diff - 如果
diff >= duration:完整吃到一轮毒素,贡献duration最后还要加上最后一次攻击带来的完整中毒时长duration。
代码编写
cpp
int findPoisonedDuration(vector<int>& timeSeries, int duration) {
if(timeSeries.empty()) return 0;
int res = 0;
for(int i = 1; i < timeSeries.size(); i++){
int diff = timeSeries[i] - timeSeries[i-1];
res += min(diff, duration);
}
res += duration;
return res;
}
题目 2:LeetCode 6. N 字形变换
题目分析
将一个字符串按照给定行数 numRows 从上往下、斜向上呈 N 字形排列,再按行读取拼接成新字符串返回。 例如 s = "PAYPALISHIRING", numRows = 3,排列后按行读得到 "PAHNAPLSIIGYIR"。 核心是模拟字符的走向:向下走到底,再斜向上走到顶,循环往复。
算法原理
- 用字符串数组,每一个元素代表一行
- 方向标记
down:true 向下,false 向上 - 走到第 0 行时,方向改为向下;走到最后一行时,方向改为向上
- 依次把每个字符追加到对应行字符串,最后把所有行拼接
边界:当 numRows == 1 的时候,直接返回原字符串,不用变换。
代码编写
cpp
string convert(string s, int numRows) {
if(numRows == 1) return s;
vector<string> rows(numRows);
int cur = 0;
bool down = false;
for(char c : s){
rows[cur] += c;
if(cur == 0 || cur == numRows - 1){
down = !down;
}
cur += down ? 1 : -1;
}
string ans;
for(auto &str : rows) ans += str;
return ans;
}
本篇总结
- 提莫攻击:区间合并类模拟,重点判断两段攻击是否重叠,取间隔和持续时间的较小值;
- N 字形变换:方向切换模拟,靠标记控制上下移动,是字符串模拟高频题;
- 模拟题核心:抓住变化规则,用变量记录当前状态,不需要复杂算法;
- 模拟题一定要优先处理特殊边界,比如行数为 1 的情况,防止下标越界。
