外观数列算法题链接
🚩了解题意
该题的下面充分的给你说明了这个题目的意思。 3 3 2 2 2 5 1 我们根据我们正常读的顺序读
俩个3 三个2 一个5 一个1
连起来就是 2 3 3 2 1 5 1 这就是最终输出的字符串。
题目开头说了,我们最初是 1开始读取。
样例是n=4,
那么我们读取4是 1211,我们读取1 只有一个1
那么2对应的值就是11(1个1的转换),
那么3就是21(2个1的转换),
4就是1211(一个2一个1的转换)
如果遇到连续相同的数字 ,我们需要总读,如果1112,我们不能三个1分开读,一个1一个1一个1一个2,这样的结果不还是1112吗,不能重复读,我们需要将连续相同的1的个数先弄清楚,1112中连续相同的1是三个,2是单独就1个。如果出现11123311,这种1不是连续的我们不用加,我们只要连续相同的,不是连续的后续出现了相同的数字也是分开读了。
所以11123311 应该读成 3个1 一个2 俩个3 俩个1.
🚩算法原理
其实从上面了解题意的过程中,我们发现一个地方
如果遇到连续相同的数字 ,需要将连续相同的数字对应的个数相加然后读。
我们针对n=5来进行思考,一组数组,我们看到有三个1,那么我们就需要写成【3 1】,然后继续接下来是2个2 ,我们就得写成【2 2】,后面是1个1,我们学成【1 1】.我们注意到,最终得到的【】花括号里前面一个数是连续相同数字的个数,后面一个数是当前的数字
前面一个数是记录连续相同数字的个数,后面的数是记录当前的数,那么我们这一题很明显是用双指针,left和right都是从0开始,遇到相同的数,right++,直到遇到不同的数,我们获取的连续相同的数字长度是right-left,然后left对应的值就是【】右边代表当前的数字,right-left就是几个,left对应的值就是几,几个几,就是这样读。然后left直接更新到right即可,然后继续循环,直到right大于这个字符串的长度即可。
right一直++,遇到right对应的值不等于left对应的值的时候,我们就更新结果,本题是数字字符,需要用到to_string将数字转成字符串,right-left=3转换成 "3",然后记录left对应的值,"3"+"1";
此时我们将left移到right对应的位置进行继续让right继续++判断。
我们的right不能一直++,到了字符串长度截至,所以我们再判断的时候,也需要加上right的移动范围的限制。
🚩实现代码
class Solution {
public:
string countAndSay(int n) {
string ret="1";//起初设置字符串是1
for(int i=1;i<n;i++)
{
string tmp;//设置临时的字符串
for(int left=0,right=0;right<ret.size();)
{
while(right<ret.size() && ret[left]==ret[right])right++;
//如果left和right对应的值相等,那么right++
tmp+=to_string(right-left)+ret[left];
//直到不相等,我们就将数字转字符right-left代表有几个相同的,再加上ret的left对应的值
left=right;//然后将right给left继续循环
}
ret=tmp;
}
return ret;
}
};
前行的路上,永远做自己光。