剑指offer之字符串题型总结

题库里关于字符串的题型大致是以下几类

  • 字符串,字符数组,整数等转换
  • 规则判断

  • 数字运算

  • 与数组操作相关

  • 动态规划

  • 高级数据结构

1.字符串,字符数组,整数等转换

(1)字符串与字符数组的转换

int main()
{
    string s = "hello";
    const char* s1 = NULL;
    //string转const char*
    s1 = s.c_str();

    char* s2 = NULL;
    const char* s3 = NULL;
    /*string转char*
     * 先将字符串转换为const char*
     * 再将const char转char
    */
    s3 = s.c_str();
    s2 = const_cast<char*>(s3);
    //string转char[],按下标挨个赋值
    char s4[10] = {0};
    for(int i = 0; i < s.length(); i++){
        s4[i] = s[i];
    }
    //const char*转string
    const char* s5 = "hello";
    string s6;
    s6 = s5;
    char* s7 = NULL;
    //char[]转其他类型都可直接赋值
}

这里要注意下const char*,char*,char[]之间的区别,对于char*他是指向一块存放这字符串内存,是不可以更改其指向内存内容,但可以改变其指向对象,char[]可读可写的。主要要注意下字符串只能转换为const char*。

(2)字符串与整数

         这里可以记住两个函数

         字符串转整数

int atoi(const char *str );

        整数转字符串

sprintf(str, "%d", rand());

2.规则判断

(1)是否符合整数规则

看剑指上的一道题:将一个字符串转换成一个整数

int StrToInt(string str) {
        const int length = str.length();
        int isNegtive = 1, overValue = 0;
        int digit = 0, value = 0;
 
        if (length == 0) return 0;
        else {
            int idx = 0;
            if (str[0] == '-') { isNegtive = -1; idx = 1;}
            else if (str[0] == '+') {idx = 1;}
 
            for (; idx<length; idx++) {
                digit = str[idx]-'0';
                // overValue表示本轮循环是否会越界
                overValue = isNegtive*value - INT_MAX/10
                          + (((isNegtive+1)/2 + digit > 8) ? 1:0);
 
                if (digit<0 || digit>9) return 0;
                else if (overValue > 0) return 0;
 
                value = value*10 + isNegtive*digit;
            }
            return value;
        }
    }

其中要注意整数的越界判断,在每次每轮循环相加前都要先判断下相加后会不会溢出

 overValue = isNegtive*value - INT_MAX/10+ (((isNegtive+1)/2 + digit > 8) ? 1:0);

(2)是否符合浮点数规则

请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100","5e2","-123","3.1416"和"-1E-16"都表示数值。 但是"12e","1a3.14","1.2.3","+-5"和"12e+4.3"都不是。

bool isNumeric(char* string)
    {
        bool sig = false;
        bool ife = false;
        bool dec = false;
        for(int i=0;i<strlen(string) ;i++){
                 if (string[i] == 'e' || string[i] == 'E') {
                if (i == strlen(string)-1) return false; // e后面一定要接数字
                if (ife) return false;  // 不能同时存在两个e
                ife = true;
            } else if (string[i] == '+' || string[i] == '-') {
                // 第二次出现+-符号,则必须紧接在e之后
                if (sig && string[i-1] != 'e' && string[i-1] != 'E') return false;
                // 第一次出现+-符号,且不是在字符串开头,则也必须紧接在e之后
                if (!sig && i > 0 && string[i-1] != 'e' && string[i-1] != 'E') return false;
                sig = true;
            } else if (string[i] == '.') {
              // e后面不能接小数点,小数点不能出现两次
                if (ife || dec) return false;
                dec = true;
            } else if (string[i] < '0' || string[i] > '9') // 不合法字符
                return false;
        }
        return true;
    }

3.数字运算

有大整数加减乘除,同上字符串转为整数,主要是注意溢出判断

4.与下表操作相关

有字符的调整,排序,替换等

(1)请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

void replaceSpace(char *str,int length) {
            //遍历一边字符串找出空格的数量
        if(str==NULL||length<0)
            return ;
        int i=0;
        int oldlen=0;//记录以前的长度
        int space=0;//记录空格的数量
        while(str[i]!='\0')
            {
               oldlen++;
               if(str[i]==' ')
                   {
                     space++;
                   }
                  i++; 
            }
        int newlen=oldlen+space*2;//插入后的长度
        if(newlen>length)//如果计算后的长度大于总长度就无法插入
            return ;
        while(oldlen>=0 && newlen>oldlen)//放字符
            {
              if(str[oldlen]==' ') //碰到空格就替换
                  {
                     str[newlen--]='0';
                     str[newlen--]='2';
                     str[newlen--]='%';
                     
                  }
               else //不是空格
               {
                    str[newlen--]=str[oldlen];
                   
               }
             oldlen--; 
             
           } 
}

思路是先计算出有的空格个数,从而算出替换后字符串的总长度,然后从后想前添加,这样每个字符移动的次数更少。

(2)输入一个字符串,按字典序打印出该字符串中字符的所有排列

void swap(char& p,char& q){
    char temp = p;
    p = q;
    q = temp;
}

void perm(string& str,vector<string>& res, int begin)
{
    if(begin == str.length()-1){
        if(find(res.begin(),res.end(),str) == res.end()){
            res.push_back(str);
        }
        return ;
    }
    else{
        for(int i=begin;i<str.length();i++){
            swap(str[begin],str[i]);
            perm(str,res,begin+1);
            swap(str[i],str[begin]);
        }
    }
}


int main()
{
    string s = "abcd";
    vector<string> res;
    int begin = 0;
    perm(s,res,begin);
    for(int i=0;i<res.size();i++){
        cout<<res[i]<<endl;
    }
    return 0;
}

思路就是递归。固定第一个字符,递归取得首位后面的各种字符串组合;再把第一个字符与后面每一个字符交换,并同样递归获得首位后面的字符串组合;递归的出口,就是只剩一个字符的时候,递归的循环过程,就是从每个子串的第二个字符开始依次与第一个字符交换,然后继续处理子串

(3)求字符的所有组合

void perm(char* str,vector<char>& res, int begin)
{
    if(begin == 0){
        for(int i=0;i<res.size();i++){
            cout<<res[i];
        }
        cout<<endl;
        return ;
    }
    if(*str == '\0')
        return ;
    res.push_back(*str);
    perm(str+1,res,begin-1);
    res.pop_back();
    perm(str+1,res,begin);

}


int main()
{
    char s[] = "abcd";
    vector<char> res;
    for(int i = 1;i <= strlen(s);i++){
        perm(s,res,i);
    }
    return 0;
}

对于n长度的字符串求其组合,则他的长度有n中,就设置循环从1到n。求长度为m的组合,那对于第一个字符,它可以添加进,那后面就再需要m-1个字符,它可以不添加进,再在后面选m个字符。

(4)将字符串循环左移n位

string LeftRotateString(string str, int n) {
         reverse(str.begin(), str.end());
        reverse(str.begin(), str.begin() + str.size() - n);
        reverse(str.begin() + str.size() - n, str.end());
        return str;
}

6.动态规划

求最长公共子串,最长公共子序列,最长回文子串,最长回文子序列等等(另写一篇总结)

7.高级算法

manached,kmp

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值