目录
-
把字符串转换成整数(剑指欧肥儿)
题目描述:将一个字符串转换成一个整数(实现Integer.valueOf(string)的功能,但是string不符合数字要求时返回0),要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0。
输入描述:输入一个字符串,包括数字字母符号,可以为空
输出描述:如果是合法的数值表达则返回该数字,否则返回0
示例一:
输入:
+2147483647 1a33
输出:
2147483647 0
解题代码一:
class Solution {
public:
int StrToInt(string str) {
//变量
int num = 0;
int i = 0;
int flag = true;
int x;
//排除字符串前面的气泡
while(str[i] == ' '){
i++;
}
//确定正负号
if(str[i] == '+'){
flag = true;
i++;
}else if(str[i] == '-'){
flag = false;
i++;
}
//开始生成数字,检查不是数字的字符
while(str[i] != '\0'){
x = flag ? 1 : -1;
if(str[i] >= '0' && str[i] <= '9'){
num = num * 10 + x * (str[i] - '0');
i++;
}else{
num = 0;
break;
}
}
return num;
}
};
解题思路:
- 排除字符串最前面的空字符' '
- 确定正负号
- 将字符串生成数字,如果含有非数字的字符,则直接返回0,方法用的是 num = num * 10 + x * (str[i] - '0')
- 这个代码,其实还是有漏洞,如果测试用例里含有溢出的数字则会报错。
解题代码二:
class Solution {
public:
int StrToInt(string str) {
//变量
int num = 0;
int i = 0;
int flag = true;
int x;
//排除字符串前面的气泡
while(str[i] == ' '){
i++;
}
//确定正负号
if(str[i] == '+'){
flag = true;
i++;
}else if(str[i] == '-'){
flag = false;
i++;
}
//开始生成数字,检查不是数字的字符
while(str[i] != '\0'){
x = flag ? 1 : -1;
if(str[i] >= '0' && str[i] <= '9'){
num = (num << 1) + (num << 3) + (str[i] & 0xf);
i++;
}else{
num = 0;
break;
}
}
return num * x;
}
};
解题思路:
- 这个代码和代码一的代码唯一的不同是,num = (num << 1) + (num << 3) + (str[i] & 0xf);这段代码的含义和 num = num * 10 + (str[i] - '0');的含义一模一样,但是没有符号,所以最后return的时候是 乘上了符号的num。
- 位运算的好处是比乘法运算效率高了那么一点点点点。
- (num << 1) + (num << 3)就是 num*10,字符'0'到'9'的ascii值的低4个二进制位刚好就是0到9所以str[i]&0xf等于str[i]-'0',如下图所示。
-
第一个只出现一次的字符(剑指欧肥儿)
题目描述:在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).
解题代码:
class Solution {
public:
int FirstNotRepeatingChar(string str) {
int x;
map<char, int> m;
int size = str.size();
for(int i = 0; i < size; i++){
m[str[i]]++;
}
for(int i = 0; i < size; i++){
if(m[str[i]] == 1){
return i;
}
}
return -1;
}
};
解题思路:
- 判断英文字符出现次数这种题,第一个反应就是要么用数组,要么用哈希表。所以,对于这道题,我们用更方便和容易理解的哈希表。
- 又因为,要判断第一个唯一字符出现的位置,那么我们首先肯定要遍历完整个字符串才可以得到,哪些字母是唯一出现的,然后再遍历一遍整个字符串,看哪个字符串在哈希表里是1,只要遇到是1的字符,立刻返回得到的值。如果,遍历完整个字符串也没有遇到哈希表键对应的值为1的字符,那么最后只能返回-1,这个-1还包括字符串长度为0的情况。
-
左旋转字符串(剑指欧肥儿)
题目描述:汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。是不是很简单?OK,搞定它!
解题代码:
class Solution {
public:
string LeftRotateString(string str, int n) {
string pre = "";
string aft = "";
if(n < 0) return NULL;
if(n == 0) return str;
for(int i = 0; i < n; i++){
pre = pre + str[i];
}
for(int i = n; i < str.length(); i++){
aft = aft + str[i];
}
aft = aft + pre;
return aft;
}
};
解题思路:
- 这道题太简单了,只要明白操作字符串的几个函数就可以,不过这里并不需要用操作字符串的函数。
- 两个for循环把前n个字符往后颠倒放置。
-
字符流中第一个不重复的字符(剑指欧肥儿)
题目描述:请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。
输出描述:如果当前字符流没有存在出现一次的字符,返回#字符。
解题代码一:
class Solution
{
public:
//Insert one char from stringstream
void Insert(char ch)
{
s.push_back(ch);
}
//return the first appearence once char in current stringstream
char FirstAppearingOnce()
{
map<char, int>m;
for(int i = 0; i < s.size(); i++){
if(!m[s[i]]){
m[s[i]] = 1;
}else{
m[s[i]]++;
}
}
for(int i = 0; i < s.size(); i++){
if(m[s[i]] == 1){
return s[i];
}
}
return '#';
}
private:
vector<int> s;
};
解题思路:
- 这道题的解题思路和“编程题——真题训练三(AQY)”里的“删除重复字符”这一道题很像。
- 这里迷惑人的地方就是,把输入字符串拆成了一个函数。实际上就是一个输入函数(功能是:一个一个输入字符)。
解题代码二:
class Solution
{
public:
//Insert one char from stringstream
void Insert(char ch)
{
s = s + ch;
hash[ch]++;
}
//return the first appearence once char in current stringstream
char FirstAppearingOnce()
{
char n = '#';
for(int i = 0; i < s.length(); i++){
if(hash[s[i]] == 1){
return s[i];
}
}
return n;
}
private:
string s;
int hash[256] = {0};
};
解题思路:
- 这个代码和上个代码的解题思路也是一模一样的。
- 但是在这里提出来说,是因为hash[256]这个int型变量,它的作用和上一个代码的map的作用是一样的,但是为什么是hash[256]呢?因为,ASCII码一共就有255个。