目录
替换所有的问号
题解:
提莫攻击
题解:
Z字形变换
题解:
外观数列
题解:
数青蛙
题解:
替换所有的问号
1576. 替换所有的问号 - 力扣(LeetCode)https://leetcode.cn/problems/replace-all-s-to-avoid-consecutive-repeating-characters/description/
题解:
遍历字符串,找到字符串中的 ?,把 ?替换成字母,且替换后的字母不能和 ?的前一个字符和后一个字符相同。
这道题主要是边界的处理,如果字符串的第一个字符为 ?,那么替换后的字符只需要和后一个字符不相同,如果字符串的最后一个字符为 ?,替换后的字符只需要和前一个字符不相同,否则会越界访问。
下面的 if 写的很妙,很好的处理了边界情况!
class Solution {
public:
string modifyString(string s) {
int n=s.size();
for(int i=0;i<n;i++)
{
if(s[i]=='?')
{
for(char ch='a';ch<='z';ch++)//26个字母逐个尝试
{
if((i==0 || s[i-1]!=ch)&&(i==n-1 || s[i+1]!=ch))//与前一个、后一个字母均不相等
{
s[i]=ch;
break;
}
}
}
}
return s;
}
};
提莫攻击
495. 提莫攻击 - 力扣(LeetCode)https://leetcode.cn/problems/teemo-attacking/description/
题解:
主要还是处理边界,不要越界访问了!
class Solution {
public:
int findPoisonedDuration(vector<int>& timeSeries, int duration) {
int n=timeSeries.size();
int ret=0;
for(int i=1;i<n;i++)
{
//在中毒影响结束前再次攻击
if(timeSeries[i]-timeSeries[i-1]<=duration) ret+=(timeSeries[i]-timeSeries[i-1]);
else ret+=duration;//在中毒影响结束后攻击
}
ret+=duration;//需要判断最后一次攻击的中毒时间
return ret;
}
};
Z字形变换
6. Z 字形变换 - 力扣(LeetCode)https://leetcode.cn/problems/zigzag-conversion/description/
题解:
本题只需要找出 Z 字形变换的规律就可以得到解。
Z字形变换后,观察第一行和最后一行的下标,发现下标的间隔都是固定的,
间隔 d = 2*numRows-2
观察Z字形变换后的中间 k 行,发现在每一行中,它们是间隔着有规律的,是间隔着递增的,
比如 numRows=3 时,在第2行中,1+3=4=d,5=1+d,7=3+d,9=5+d,11=7+d
numRows=4 时,在第 2 行中,1+5=6=d,7=1+d,11=5+d,13=7+d
在第 3 行中,2+4=6=d,8=2+d,10=4+d
首先我们需要找到第 k 行( k 从 1 开始)的两个起始下标 i 和 j,i+j = d,而 i = k,则 j = d-k,之后 i +=d , j += d,注意边界的处理!
class Solution {
public:
string convert(string s, int numRows) {
if(numRows==1) return s;
int d=2*numRows-2,n=s.size();
string ret;
//处理第一行
for(int i=0;i<n;i+=d)
ret+=s[i];
//处理中间行
for(int k=1;k<numRows-1;k++)
{
for(int i=k,j=d-k;i<n||j<n;i+=d,j+=d)
{
//注意for循环的条件判断为或
if(i<n) ret+=s[i];//判断越界
if(j<n) ret+=s[j];
}
}
//处理最后一行
for(int i=numRows-1;i<n;i+=d)
ret+=s[i];
return ret;
}
};
外观数列
38. 外观数列 - 力扣(LeetCode)https://leetcode.cn/problems/count-and-say/description/
题解:
这道题主要是理解题目的意思。
给了一个初始字符串 1,按照 “ 1 个 1 ”,把字符串压缩为 “ 11 ”,再继续按照 “ 2 个 1”,把字符串压缩为 “ 21 ”,继续按照 “ 1 个 2 ,1 个 1 ” ,把字符串压缩为 “ 1211 ”,以此类推即可。
用双指针来遍历字符串,找出相同数字的个数即可。
class Solution {
public:
string countAndSay(int n) {
string s="1";
while(--n)
{
string tmp;
int len=s.size();
for(int left=0,right=0;right<len;)
{
while(right<len && s[left]==s[right]) ++right;
tmp+=(to_string(right-left)+s[left]);
left=right;
}
s=tmp;
}
return s;
}
};
数青蛙
1419. 数青蛙 - 力扣(LeetCode)https://leetcode.cn/problems/minimum-number-of-frogs-croaking/description/
题解:
这道题的意思就是 croak 这个单词会在字符串中交叉着出现,但是字符串里面一定只有 croak 这五个字母,否则就是无效的字符串。
我们遍历字符串:
- 如果出现的是 c,那么需要判断它是由一只新的青蛙唱的,还是可以由已经唱完的青蛙来唱,唱完的青蛙上一次唱的一定是 k,所以如果 k 的次数不为 0,那么就可以由已经唱完的青蛙来唱,否则就只能由一只新的青蛙来唱。
- 如果出现的是 r、o、a、k,那么则需要判断它们的前驱字符有没有唱,如果唱过了,说明字符串的 croak 没有缺字母,如果没唱过,则说明 croak 缺字母了,字符串是无效的,返回 -1。
- 利用数组来标记字符有没有唱过,唱过了就标记唱过的次数,没唱过就是 0.
代码主要学习用数组和哈希表建立一个映射关系,映射关系如下:
class Solution {
public:
int minNumberOfFrogs(string croakOfFrogs) {
string t="croak";
int n=t.size();
vector<int> hash(n);//哈希表,记录字母出现的次数
unordered_map<char,int> index;
for(int i=0;i<n;i++)
index[t[i]]=i;//c->0,r->1,o->2,a->3,k->4
for(auto x:croakOfFrogs)
{
if(x=='c')
{
if(hash[n-1]!=0) hash[n-1]--;
hash[0]++;
}
else
{
int i=index[x];
if(hash[i-1]==0) return -1;//不配对
hash[i-1]--; hash[i]++;
}
}
for(int i=0;i<n-1;i++)
{
if(hash[i]!=0) return -1;
}
return hash[n-1];
}
};