编程题——关于字符串

 

目录

 

把字符串转换成整数(剑指欧肥儿)

第一个只出现一次的字符(剑指欧肥儿)

左旋转字符串(剑指欧肥儿)

字符流中第一个不重复的字符(剑指欧肥儿)


  • 把字符串转换成整数(剑指欧肥儿)

题目描述:将一个字符串转换成一个整数(实现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;
    }
};

解题思路:

  1. 排除字符串最前面的空字符' '
  2. 确定正负号
  3. 将字符串生成数字,如果含有非数字的字符,则直接返回0,方法用的是 num = num * 10 + x * (str[i] - '0')
  4. 这个代码,其实还是有漏洞,如果测试用例里含有溢出的数字则会报错。

解题代码二:

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;
    }
};

解题思路:

  1. 这个代码和代码一的代码唯一的不同是,num = (num << 1) + (num << 3) + (str[i] & 0xf);这段代码的含义和 num = num * 10 +  (str[i] - '0');的含义一模一样,但是没有符号,所以最后return的时候是 乘上了符号的num。
  2. 位运算的好处是比乘法运算效率高了那么一点点点点。
  3. (num << 1) + (num << 3)就是 num*10,字符'0'到'9'的ascii值的低4个二进制位刚好就是0到9所以str[i]&0xf等于str[i]-'0',如下图所示。
  4. 编程题——关于字符串_第1张图片

 


  • 第一个只出现一次的字符(剑指欧肥儿)

题目描述:在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).

解题代码:

class Solution {
public:
    int FirstNotRepeatingChar(string str) {
        int x;
        map 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. 判断英文字符出现次数这种题,第一个反应就是要么用数组,要么用哈希表。所以,对于这道题,我们用更方便和容易理解的哈希表。
  2. 又因为,要判断第一个唯一字符出现的位置,那么我们首先肯定要遍历完整个字符串才可以得到,哪些字母是唯一出现的,然后再遍历一遍整个字符串,看哪个字符串在哈希表里是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;
    }
};

解题思路:

  1. 这道题太简单了,只要明白操作字符串的几个函数就可以,不过这里并不需要用操作字符串的函数。
  2. 两个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()
    {
        mapm;
        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 s;
};

解题思路:

  1. 这道题的解题思路和“编程题——真题训练三(AQY)”里的“删除重复字符”这一道题很像。
  2. 这里迷惑人的地方就是,把输入字符串拆成了一个函数。实际上就是一个输入函数(功能是:一个一个输入字符)。

解题代码二:

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};
};

解题思路:

  1. 这个代码和上个代码的解题思路也是一模一样的。
  2. 但是在这里提出来说,是因为hash[256]这个int型变量,它的作用和上一个代码的map的作用是一样的,但是为什么是hash[256]呢?因为,ASCII码一共就有255个

 

你可能感兴趣的:(算法题,剑指欧肥儿,字符串)