【算法】模拟:(leetcode)38.外观数列(medium)

 本篇使用c++

目录

1、题目链接

2、题目介绍

3、解法

1) 理解题目和定义

2)实现步骤

a. 定义一个辅助函数 dispose(string x)

b. 实现 countAndSay(int n) 函数

4、代码

💗感谢阅读!💗


1、题目链接

38. 外观数列 - 力扣(LeetCode)

2、题目介绍

「外观数列」是一个数位字符串序列,由递归公式定义:

  • countAndSay(1) = "1"
  • countAndSay(n) 是 countAndSay(n-1) 的行程长度编码。

行程长度编码(RLE)是一种字符串压缩方法,其工作原理是通过将连续相同字符(重复两次或更多次)替换为字符重复次数(运行长度)和字符的串联。例如,要压缩字符串 "3322251" ,我们将 "33" 用 "23" 替换,将 "222" 用 "32" 替换,将 "5" 用 "15" 替换并将 "1" 用 "11" 替换。因此压缩后字符串变为 "23321511"

给定一个整数 n ,返回 外观数列 的第 n 个元素。

示例 1:

输入:n = 4

输出:"1211"

解释:

countAndSay(1) = "1"

countAndSay(2) = "1" 的行程长度编码 = "11"

countAndSay(3) = "11" 的行程长度编码 = "21"

countAndSay(4) = "21" 的行程长度编码 = "1211"

3、解法

1) 理解题目和定义

首先,需要理解题目中的“外观数列”和“行程长度编码(RLE)”的概念。

  • 外观数列是一个数位字符串序列,其中每个元素都是前一个元素的行程长度编码。
  • 行程长度编码是一种字符串压缩方法,它通过计算连续相同字符的数量来压缩字符串。

例如,

给定字符串 "112223",其行程长度编码为 "213213",因为有两个'1',一个'2'(但这里实际上是连续的两个'2',所以编码为'22'),然后又是三个'2',最后是一个'3'。

但注意,这里我们实际上在编码时,每遇到一组连续相同的字符,就将其数量和该字符一起编码,而不是先编码字符再编码数量。所以,"112223" 正确的行程长度编码应为 "21321"。

2)实现步骤

a. 定义一个辅助函数 dispose(string x)

这个函数负责将输入的字符串 x 转换为它的行程长度编码

我们使用双指针法来遍历字符串,left 指针指向当前正在处理的字符的起始位置,right 指针用于寻找与 left 指针指向字符相同的连续字符的结束位置。

每找到一组连续相同的字符,我们就将其数量(right - left)和字符本身拼接成一个新的字符串片段,并添加到结果字符串 tmp 中。最后返回 tmp

string dispose(string  x)
    {
        string tmp;//临时存放编码后的字符串
        int n = x.size();
        if (n == 1)
        {
            tmp.push_back('1');
            tmp.push_back(x[0]);
            return tmp;
        }

        //双指针-->完成行程长度编码
        int left = 0, right = 1;
        while (right < x.size())
        {
            while (right < x.size() && x[right] == x[left])
            {
                right++;
            }
            string ch = to_string(right - left);
            tmp += ch + x[left];
            left = right;
        }
        return tmp;
    }
b. 实现 countAndSay(int n) 函数

这个函数是主函数,用于生成外观数列的第 n 个元素。

  • 首先,我们初始化结果字符串 ret 为 "1",因为 countAndSay(1) 的结果就是 "1"。
  • 然后,使用一个循环从 2 循环到 n,在每次循环中,都将当前的 ret 字符串传递给 dispose 函数进行编码,并将返回的结果重新赋值给 ret。这样,经过 n-1 次迭代后,ret 就是我们要找的第 n 个外观数列元素。
string countAndSay(int n) {
        string ret("1");
        if (n == 1)
        {
            return  ret;
        }

        
        for (int i = 2; i <= n; i++)
        {
            ret = dispose(ret);
        }
        return ret;
    }

4、代码

class Solution {
public:
    string dispose(string  x)
    {
        string tmp;//临时存放编码后的字符串
        int n = x.size();
        if (n == 1)
        {
            tmp.push_back('1');
            tmp.push_back(x[0]);
            return tmp;
        }

        //双指针-->完成行程长度编码
        int left = 0, right = 1;
        while (right < x.size())
        {
            while (right < x.size() && x[right] == x[left])
            {
                right++;
            }
            string ch = to_string(right - left);
            tmp += ch + x[left];
            left = right;
        }
        return tmp;
    }
    string countAndSay(int n) {
        string ret("1");
        if (n == 1)
        {
            return  ret;
        }

        
        for (int i = 2; i <= n; i++)
        {
            ret = dispose(ret);
        }
        return ret;
    }
};

💗感谢阅读!💗


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值