题一:替换所有的问号![](https://i-blog.csdnimg.cn/blog_migrate/2e59fb5f6cc88b1d77d9f0dc78e5805c.png)
1.链接
2.思路
这道题,最重要的就是理解什么是连续重复的字符
连续重复字符是指:相同字母连在一起多次出现
- 先遍历这个数组,去找到 ?出现的位置
- 找到后,就对该位置进行替换,替换的原则是:不和左右的字母相同即可
- 当找到了一个符合原则的字母,就退出循环
- 完成这个操作后,在继续往后面去找?出现的位置,继续上面操作
边界问题
由于这里会进行对 i -1 和 i + 1 位置的访问,为了避免出现数组越界访问,就单独处理 ? 出现在第一个位置和最后一个位置的情况
3.代码
class Solution {
public:
string modifyString(string s) {
int n = s.size();
//当?出现在第一个位置
if (s[0] == '?') {
for (int i = 0; i <= 26; i++) {
if (s[1] != i + 'a') {
s[0] = i + 'a';
break;
}
}
}
//当?出现在中间位置
for (int i = 1; i < n; i++) {
if (s[i] == '?') {
for (int j = 0; j <= 26; j++)
if (s[i - 1] != j + 'a' && s[i + 1] != j + 'a') {
s[i] = j + 'a';
break;
}
}
}
//当?出现在最后一个位置
if (s[n-1] == '?' && n >= 2) {
for (int i = 0; i <= 26; i++) {
if (s[n - 2] != i + 'a') {
s[n - 2] = i + 'a';
break;
}
}
}
return s;
}
};
题二:提莫攻击
1.链接
2.思路
- 我们定义一个变量 sum,用来累加每次攻击所造成的中毒的时长。
- 问题的关键就是:发动攻击后,中毒时间该如何去算。此刻我们要将相邻二次攻击的时间差 ( gap )和中毒持续时间进行比较。
- 当 gap >= 中毒持续时间,那么就可以完成本次中毒所要时间
- 当 gap < 中毒持续时间,那么就会发生,本次攻击所造成的中毒还没有结束,就又开始了一次攻击,那么此刻我们去计算本次攻击所造成的中毒时间就等于 gap
本题的关键就是如何去累积算 sum ,这里我们要正确确定好每次计算中毒时长的范围。
sum 统计的是因为本次攻击所造成的中毒时长。
3.代码
class Solution {
public:
int findPoisonedDuration(vector<int>& timeSeries, int duration) {
int sum = 0;
for (int i = 0; i < timeSeries.size() - 1; i++) {
int gap = timeSeries[i + 1] - timeSeries[i];
if (gap >= duration)
sum += duration;
else
sum += gap;
}
return sum + duration;
}
};
题三:Z字形变换
1. 链接
2.思路
这里的 Z 字形应该说是 N 字形更好。先从上往下,然后在沿对角线方向,在不断循环这个操作,直到没有字符
我们输出时,先输出第一行的,并按照从左往右的方向去输出,然后就是下一行,并也是按照从左往右去输出,这样重复操作,直到输完最后一行。
我们可以去观察原字符串数组下标与最后输出字符串的下标 ,行数的关系。
- 第一行和最后一行下标的关系是,同一行相邻二个数据下标之差等于:2*numRows - 2
- 当为中间的行数时,以示例二为例子,其Z字形的第二行为 A L S I G
- 其中 A 与 L 之间的下标差距为2*行数 - 2 ,这里的行数是:此刻黑色方框所对应的Z字形的行数
- L与S之间的下标差为:2 * 当前所处的行数
3.代码
class Solution {
public:
string convert(string s, int numRows) {
if (numRows == 1)
return s;
string ret;
int gap = 2 * numRows - 2;
for (int i = 0; i < numRows; i++) {
int add = 2 * i, index = i;
while (index < s.size()) {
ret += s[index];
add = gap - add;// 第一次间距是step -2*i,第二次是2*i,
index += (i == 0 || i == numRows - 1) ? gap : add;
}
}
return ret;
}
};
题四: 外观数列
1.链接
2.思路
核心思路:模拟+双指针操作
3.代码
class Solution {
public:
string countAndSay(int n) {
string ret = "1";
for (int i = 1; i < n; i++) //只要进行n-1次操作
{
int left = 0, right = 0;
string tmp;
while (right < ret.size()) {
while (ret[right] == ret[left] && right < ret.size()) {
right++;
}
//出这个循环时,就代表此刻right所对应的值和left所对应的值不同
tmp += to_string(right - left) + ret[left];
left = right;
}
ret = tmp;
}
return ret;
}
};