Leetcode 38:报数

本文深入解析LeetCode第38题报数序列的算法实现,包括迭代和递归两种方法,详细解释了每一步的逻辑,并讨论了C++中的sprintf_s与sprintf、strlen与sizeof的区别,以及char与string类型的转换。通过具体代码示例,展示了如何通过递归和迭代的方式生成报数序列。

题目描述

报数序列是一个整数序列,按照其中的整数的顺序进行报数,得到下一个数。其前五项如下:

  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”

我的解法

string countAndSay(int n) {
	string last_count;
	string now_count;
	if (n == 1){ return "1"; }
	if (n == 2){ return "11"; }
	last_count = "11";
	for (int i = 3; i <= n; i++) //第几次报数的循环
	{
		int j = 0;  // 慢指针

		now_count = "";
		while (j < last_count.size() - 1)
		{
			int temp = 1;  // 重复个数
			int k = j + 1;  // 快指针
			while (last_count[j] == last_count[k])
			{
				temp++;
				k++;
			}
			char temp_char[10];
			sprintf_s(temp_char, "%d", temp);
			now_count = now_count + temp_char;
			now_count.push_back(last_count[j]);
			j = k;
		}

		// 处理最后一位
		if (last_count[last_count.size() - 1] != last_count[last_count.size() - 2])
		{
			now_count.push_back('1');
			now_count.push_back(last_count[last_count.size() - 1]);
		}
		last_count = now_count;
	}
	return now_count;
}
  • 思考延伸
  1. sprintf和sprintf_s
    sprintf_s是sprintf的安全版本,指定缓冲区长度来避免sprintf()存在的溢出风险,主要差在sprintf_s第二个参数,可以控制缓冲区大小
  2. strlen(*char) 和sizeof()
    strlen(*char)函数求是字符串的实际长度,它可以用来获取动态实际字符数组的长度,是从开始到遇到第一个“\0”,如果只是定义没有赋予初始值,这个结果是不确定的,它会从数组的首地址开始一直找下去,直到遇到“\0”停止查找。
    sizeof()求所占总空间的字节数,静态的,跟初始状态字符数组的大小有关系,大小等于初始时字符数组的大小或者等于初始时字符数组的大小+1。
  3. C++中char类型可以自动转换成string类型,即你可以用char类型字符串直接给string类型变量赋值。但反过来是不行的。

递归解法

思路:用的递归思想,观察发现每一个结果和前一个结果有关,出口是第一个报数。

string countAndSay1(int n)
{
	if (n == 1){ return "1"; }
	string str_last = countAndSay(n - 1);
	string str_now;
	int count = 1;
	for (int i = 0; i < str_last.size(); i++)
	{
		if (str_last[i] == str_last[i + 1])
		{
			count++;
		}
		else
		{
			str_now += to_string(count) + str_last[i];
			count = 1;
		}
	}
	return str_now;
}
  • 我的疑惑
    对于字符串strlast访问到第strlast.size()个元素不会报数组溢出bug吗?

  • 解答
    字符串实际上是使用 null 字符 ‘\0’ 终止的一维字符数组。因此,一个以 null 结尾的字符串,包含了组成字符串的字符。
    因此最后字符串的末尾还是会有一个‘\0’字符,因此不会有溢出的bug,当然再往后访问一个就出错了。

  • 其它收获

  1. 递归思想:程序的下一层输入为上一层的输出,即函数参数为上一次函数运算的返回值
  2. to_string函数:.c++11标准增加了全局函数std::to_string
内容概要:本文系统研究了构网型变流器的正负序阻抗解耦特性及其在弱电网环境下的稳定性表现,重点依托Matlab/Simulink仿真平台,构建了详细的阻抗数学模型,设计了解耦控制策略,并采用小信号扫频法进行频域辨识与稳定性验证。研究深入探讨了构网型变流器与传统跟网型逆变器在正负序阻抗特性上的本质差异,结合虚拟同步发电机(VSG)等先进控制技术,分析其在抑制宽频带振荡、削弱锁相环动态耦合等方面的优越性。文中不仅提供了完整的仿真模型与MATLAB代码实现,还整合了光伏、风电、储能、微电网等多类新能源系统的阻抗建模与稳定性分析资源,形成了一套面向新型电力系统稳定性的综合性技术资料体系,具有较强的科研复现与工程参考价值。; 适合人群:面向具备电力电子、电力系统自动化、新能源并网等专业背景的研究生、高校教师及工程技术人员,特别适用于从事阻抗建模、小干扰稳定性分析、宽频振荡机理研究以及撰写高水平学术论文的科研工作者。; 使用场景及目标:①掌握构网型变流器正负序阻抗建模与扫频辨识的仿真方法;②深入理解VSG等构网型控制在弱电网中提升稳定性的内在机理;③复现顶刊论文中的阻抗分析流程与稳定性判据应用;④利用提供的成熟模型与代码加速科研进程,支撑课题研究与学术成果产出。; 阅读建议:建议结合文中提供的Simulink模型与MATLAB代码,按照“理论建模—仿真搭建—扫频激励—频响提取—Nyquist判据分析”的完整流程进行实践操作,重点关注扫频信号的注入方式、频率范围设置及阻抗曲线的物理意义解读,并参考博士论文复现案例深化对复杂动态耦合问题的理解。
已经博主授权,源码转载自 https://pan.quark.cn/s/82d496e9a0de Linux C/C++基础学习资料对于IT领域的初学者和开发者而言是至关重要的资源,其中包含了操作系统、编程语言以及算法等多个核心知识领域。本文将深入剖析这些主题,旨在帮助你更加透彻地领悟和掌握相关技能。 让我们从“Linux命令详解”部分开始。Linux命令行是操作系统的核心工具,精通各类命令能够显著提升开发效率。例如,“ls”用于列出目录内容,“cd”用于切换工作目录,“grep”用于在文件中检索特定文本,“vi/vim”是常用的文本编辑器,而“gcc/g++”则是C/C++的编译工具。熟悉并高效运用这些基础命令是Linux环境下编程的入门关键。 接下来是“Linux下编程环境”的配置。在Linux平台上进行C/C++程序的开发,需要安装相关的开发工具,例如GCC/G++编译器、Make构建工具、GDB调试器等。同时,理解环境变量的设置、编译与链接过程、动态库与静态库的运用也是搭建编程环境的重要环节。此外,掌握使用版本控制系统如Git进行代码管理,也是当代开发者不可或缺的技能。 然后是C/C++的基础知识。C++作为C语言的延伸,支持面向对象的编程范式,而C语言则是系统级编程的基础。掌握变量、数据类型、运算符、控制结构(包括if-else、for、while等)、函数、指针、数组、结构体等基本概念是C/C++学习的根本。对于C++,还需熟悉类、对象、继承、多态、模板等高级特性。 “数据结构”是编程中的核心概念,涵盖了数组、链表、栈、队列、哈希表、树(如二叉树、红黑树等)以及图等。深入理解这些数据结构的特性与操作,以及它们在实际问题中的具体应用,能够有效增强解决问题的能力。...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值