Leetcode报数算法与分析

本文介绍LeetCode上的报数序列题目,并提供一种高效解题思路。文章详细解析了如何利用逆向思维简化问题,避免复杂的递归,通过双层循环实现报数序列的生成。

@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输出,而要使用已定义的字符串通过赋值来正确地输出字符串。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值