[LeetCode]Count And Say
题目
思路
这个题目是一个easy级别,算法本身没有难点,但是C++的语法有几点需要注意。下面分别说一下:
LeetCode中给的C++函数原型是这样的
string countAndSay(int n);
也就是说给一个n得到一个string类型的数字串,但是n和这个数字串似乎没有什么关系,这个数字串是从上一个数字串推到过来的,所以基本上确定要递归。
看这个函数原型的返回类型是string的,乍一看到这个string我有点蒙,把C++和Java的东西弄混了。先说java,因为返回的string是一个类对象,它返回一个在堆上开辟的对象的引用,所以countAndSay函数外面的地方依然能很容易的看到这个对象,只要把引用赋值给一个string类型的引用。同时在countAndSay内部开辟的string对象空间也不用手动的释放,因为有GC。但是C++情况不一样,它没有GC,要考虑堆内存的手动释放,所以有点纠结。后来查了一下,说一下C++怎么实现的。
对于上面的这个函数,它返回的不是原来堆或栈内存中对象的引用,而是返回了这个对象本身。函数外面调用这个方法的时候,会调用string类的拷贝构造函数进行其他string对象的初始化,然后countAndSay里面的string类对象就被回收了。具体是谁回收的,从函数原型看到这里并没有指针或者引用,所以对象并没有必要在堆中开辟内存,在栈中足够了。既然是在栈中开辟的string对象的存储空间,那么这个string对象就随着函数栈的变化自动的回收了。具体的看下面这篇博文:
在返回值赋值给外部的string对象的时候,调用了string类的拷贝构造函数或者赋值符函数。
C++构造/析构/赋值运算
同时,CountAndSay中用到一些string类的方法。
标准C++中string类的使用
标准C++中提供的string类得功能也是非常强大的,一般都能满足我们开发项目时使用。
要想使用标准C++中string类,必须要包含
#include <string>// 注意是<string>,不是<string.h>,带.h的是C语言中的头文件 using std::string; using std::wstring; 或 using namespace std;
下面你就可以使用string/wstring了,它们两分别对应着char和wchar_t。
string和wstring的用法是一样的,以下只用string作介绍:
string类的构造函数:
string(const char *s); //用c字符串s初始化 string(int n,char c); //用n个字符c初始化 此外,string类还支持默认构造函数和复制构造函数,如string s1;string s2="hello";都是正确的写法。当构造的string太长而无法表达时会抛出length_error异常 ;
string类的字符操作:
const char &operator[](int n)const; const char &at(int n)const; char &operator[](int n); char &at(int n); operator[]和at()均返回当前字符串中第n个字符,但at函数提供范围检查,当越界时会抛出out_of_range异常,下标运算符[]不提供检查访问。 int size()const; //返回当前字符串的大小
Vector中的两个函数
string countAndSay(int n) { if(n == 1) return "1"; string analyzeStr = countAndSay(n - 1); int count = 1; string resultStr; int preInt = analyzeStr[0] - '0'; for(int i = 1; i < analyzeStr.size(); i++) { int curInt = analyzeStr[i] - '0'; if(preInt == curInt) { count++; } else { resultStr.push_back(count + '0'); resultStr.push_back(preInt + '0'); preInt = curInt; count = 1; } }//for resultStr.push_back(count + '0'); resultStr.push_back(preInt + '0'); return resultStr; }
代码下载地址
https://github.com/stemon/LeetCode/blob/master/countAndSay.cpp