(1)数组排成最小的数(剑指offer33/leetcode179)
解题思路:关于数字的大数问题最终都要转换成字符串解决。在该题中,将vector
static bool cmp(const string str1, const string str2){
string s1 = str1 + str2;
string s2 = str2 + str1;
if(s1.compare(s2)>0)
return true;
else
return false;
}
就可以将字符串数组进行排序,然后依次相连接即可。
(2)哈希表的使用(剑指offer35、55,leetcode242)
使用场景:当顺序遍历一个string,其中一次字符遍历可能会用到之前字符遍历结果的时候,就可以使用哈希表(如果不使用哈希表,可能就需要双重遍历);
-------int hashtable[256],手动构造(字符ASCII值为索引,字符在字符串中索引或者count次数为值)
-------unordered_map
(3)字符串的简单操作(插入、删除字符,旋转)
插入删除的时候,为了避免多次移动,可以采用“倒着”复制的技巧(剑指offer4):先遍历一遍字符串,统计总共需要
增加的次数,然后从末尾处开始向前进行操作;
字符串的翻转(
变形:单词翻转,左旋字符串(剑指offer42)
“I am a student”------->"student a am I"
解题思路:①先翻转整个字符串,变成"tneduts a ma I"
②然后翻转每一个空格符号间隔开的单词
"abcdefg"----2---->"cdefgab"
解题思路:①先分成两部分旋转字符串,变成"ba|gfedc"
②然后将整个字符串旋转
(4)字符串的匹配
正则表达式匹配(剑指offer53)
递归的使用;
需要考虑清楚当后一个pattern为'*'时该如何匹配;代码如下:
bool match(const string pattern,const string str,int pattern_begin,int str_begin)
{
if(pattern_begin==pattern.length() && str_begin==str.length())
return true;
if(pattern_begin==pattern.length() && str_begin!=str.length())
return false;
if(pattern_begin!=pattern.length() && str_begin==str.length() && pattern.at(pattern_begin)!='*')
return false;
if(pattern_begin!=pattern.length() && str_begin==str.length() && pattern.at(pattern_begin)=='*')
return true;
if(pattern_begin!=pattern.length()-1 && pattern.at(pattern_begin+1)=='*')
{
if(pattern.at(pattern_begin)==str.at(str_begin))
return match(pattern,str,pattern_begin+2,str_begin+1) ||
match(pattern,str,pattern_begin,str_begin+1) ||
match(pattern,str,pattern_begin+2,str_begin);
else if(pattern.at(pattern_begin)=='.' && str_begin!=str.length())
return match(pattern,str,pattern_begin+2,str_begin+1) ||
match(pattern,str,pattern_begin,str_begin+1) ||
match(pattern,str,pattern_begin+2,str_begin);
else
return match(pattern,str,pattern_begin+2,str_begin);
}
else if(pattern.at(pattern_begin)==str.at(str_begin)
||pattern.at(pattern_begin)=='.' && str_begin!=str.length())
return match(pattern,str,pattern_begin+1,str_begin+1);
else
return false;
}
需要考虑清楚:第一个字符为正负号、小数点、e或者E
//判断剩余的部分是不是科学计数法
bool isExponential(char** string)
{
if(**string != 'e' && **string != 'E')
return false;
(*string)++;
if(**string == '+' || **string == '-')
(*string)++;
if(**string == '\0')
return false;
while(**string != '\0' && **string >= '0' && **string <= '9')
(*string)++;
return (**string == '\0')?true:false;
}
bool isNumber(char* string)
{
if(string==NULL)
return false;
if(*string == '+' || *string == '-')
string++;
if(*string == '\0')
return false;
bool num = true;
while(*string != '\0' && *string >= '0' && *string <= '9')
string++;
if(*string != '\0')
{
if(*string == '.')
{
string++;
while(*string != '\0' && *string >= '0' && *string <= '9')
string++;
if(*string == 'e' || *string == 'E')
num=isExponential(&string);
}
else if(*string == 'e' || *string == 'E')
num = isExponential(&string);
else
num=false;
}
return num&&(*string == '\0');
}
打印1到最大n位数(剑指offer12)
解题思路:用一个字符串表示一个大数,分别实现increase(模拟数字++),is_max(是否已经到达最大),print
代码如下:
bool is_max(char* str, int n)
{
int count = 0;
while(str[count]=='9')
count++;
if(count==n)
return true;
else
return false;
}
void incre(char* str,int n)
{
int token=n-1;
for(int i=n-1;i>=0;i--)
{
if(token==i && str[i]=='9')
{
str[i]='0';
token--;
}
else if(token==i)
{
str[i]++;
break;
}
}
}
void print(char* str,int n)
{
bool first0 = false;
for(int i=0;i
可以采用回溯的思想,将第一个字符分别与后面的字符进行替代,然后递归,代码如下:
void arrange(string str, int index)
{
if(index == str.length()-1)
cout << str << endl;
else{
for(int i = index; i < str.length(); ++i){
swap(str.at(index), str.at(i));
arrange(str, index+1);
swap(str.at(index), str.at(i));
}
}
}
abc的排列有:abc、acb、bac、bca、cab、cba
abc的组合有:a、b、c、ab、ac、bc、abc
同样也是采用回溯的解法:依次求出长度为1,2,....,n的组合
n个字符长度为m的组合问题可以转换为n-1中长度为m-1 和 n-1长度为m
string result;
void combination(const string str)
{
if(str.empty())
return;
for(int i = 1; i <= str.length(); ++i){
combinationCore(str, i, 0);
}
}
void combinationCore(const string str, int m, int index)
{
if(m > str.length()-index)
return;
if(m == 0){
cout << result <
结论:排列组合问题都可以采用回溯法解决
(7)求字符串最长回文子串(leetcode 5)
解题思路:分别统计以每一个字符为中心的奇偶回文子串长度,记录其中的最大值以及中心点;
(8)按之字形排列字符串(leetcode6)
解题思路:声明一个vector
(9)求字符串数组前缀(leetcode14)
解题思路:先对数组进行排序,然后就只需要看第一个和最后一个字符串;
(10)九键输入法转换(leetcode17)
解题思路:构造常量数组 const vector
采用回溯法。
(11)括号匹配(leetcode20)
解题思路:括号匹配的题目都可以用栈来解决。
(12)括号排列(Leetcode22)
解题思路:动态规划