@Leetcode报数
这题是到目前为止,第一个有点意思的需要脑子的题。说句实话,笔者思考许久,最多写了4个循环,最终还是被自己菜到,卑微地去向大佬们学习借鉴了一下思路,发现本题需要一个“逆向思维”,具体玄妙请看下文分解。废话少说,上题干:
报数序列是一个整数序列,按照其中的整数的顺序进行报数,得到下一个数。其前五项如下:
1、 1
2、 11
.3、 21
4、 1211
5、 111221
1 被读作 “one 1” (“一个一”) , 即 11。
11 被读作 “two 1s” (“两个一”), 即 21。
21 被读作 “one 2”, “one 1” (“一个二” , “一个一”) , 即 1211。
给定一个正整数 n(1 ≤ n ≤ 30),输出报数序列的第 n 项。注意:整数顺序将表示为一个字符串。
示例 1:
输入: 1
输出: “1”
示例 2:
输入: 4
输出: “1211”
相信大多数的和笔者一样的菜鸟,拿到题目脑子里就开始构建循环了,于是思路就一步步飘出来:我从头遍历,检查每个字符,如果他的下一个字符与之相等,count就加一,否则就更新下一个字符,重新算count。听上去头头是道,下笔一写,发现有问题循环的赋值有时候执行两步,有时候执行一步,这就很尴尬了。
于是我借鉴了一下to-be-a-better-man-3大佬的遍历思路,不需要使用复杂度高的递归,也能完成问题的解答。
链接:https://leetcode-cn.com/problems/two-sum/solution/xun-huan-bian-li-by-to-be-a-better-man-3/
下面我们可以看看他的思路:
首先进行特判,如果n就为1,那么输出也就是1,这是因为之后的判断中,是以前面一个数字为判断条件,这就是我所说的“逆向思维”,有时一些违反常规的判断方式往往能取得意想不到的效果。特判完成之后字符串可以定义为11,开始从2到n的循环,由于每次外层循环都会更新一个字符串,所以我们这里将即将算出的字符串先定为空,并且将判断的标志放在了str[0]的位置,计数器设为1(无论如何只要出现数字,至少出现1次),并开始内层从1开始一直到未更新的str的总长度的判断。
在内层判断中,如果当前值与前一个值相等,计数器加一,否则说明前一个值的数字计算已经到了最后,于是我们在新的字符串中push_back计数器的值,再push_back一下前一个值,完成这几个操作后重置计数器,并且将当前值变为接下来要比较的那个“前一个值”,继续循环判断,直到达到最大长度值。这之后得到的字符串已经替代了11成为了新的str,这时外层循环加一,继续定义新的空字符串存放下一层,如此反复直到达到目标n值。
代码如下:
class Solution {
public:
string countAndSay(int n) {
string spe="1";
if(n==1)
return spe;
string str="11";
for(int i=2;i<n;i++)
{
string newstr="";
int cou=1;
char m=str[0];
for(int j=1;j<str.length();j++)
{
if(str[j]==m)
cou++;
else if(str[j]!=m)
{
newstr.push_back(cou+'0');
newstr.push_back(m);
m=str[j];
cou=1;
}
}
newstr.push_back(cou+'0');
newstr.push_back(m);
str=newstr;
}
return str;
}
};

本题要注意的细节有以下几部分:
首先,要注意在输出计数器的值时要加上’0’,由于是往字符串中加入值,所以要注意转换成char类型。另外,在输出的时候一定是在for循环的外面,所以不能直接使用newstr输出,而要使用已定义的字符串通过赋值来正确地输出字符串。
本文介绍LeetCode上的报数序列题目,并提供一种高效解题思路。文章详细解析了如何利用逆向思维简化问题,避免复杂的递归,通过双层循环实现报数序列的生成。
5518

被折叠的 条评论
为什么被折叠?



