剑指offer(二)字符串

面试题4:替换空格

题目:请实现一个函数,将一个字符串中的空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
解题思路:先遍历一遍字符串,统计出空格的个数。然后从字符串的后面开始复制和替换,直至所有的空格都替换完毕。
举一反三:合并两个有序的数组或字符串时,可以考虑从后往前复制,这样减少移动的次数。

    void replaceSpace(char *str,int length) {
        if(str == NULL || length<=0){
            return;
        }
        int i=0;
        int originalLength = 0;
        int newLength = 0;
        int numOfBlank = 0;
        while(*(str+i) != '\0'){
            originalLength++;
            if(*(str+i) == ' ')
                numOfBlank++;
            i++;
        }
        newLength = originalLength + numOfBlank*2;
        if(newLength > length)
            return;
        int indexOfOriginal = originalLength;
        int indexOfNew = newLength;
        while(indexOfOriginal >= 0 && indexOfNew > indexOfOriginal){
            if(*(str+indexOfOriginal)==' '){
                *(str+indexOfNew)='0';
                *(str+indexOfNew-1)='2';
                *(str+indexOfNew-2)='%';
                indexOfNew -= 3;
            }else{
                *(str+indexOfNew) = *(str+indexOfOriginal);
                indexOfNew--;
            }
            indexOfOriginal--;
        }        
    }

面试题28:字符串的排列

题目:输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
解题思路:把整个字符串分成两部分,一部分是字符串的第一个字符,另一个部分是第一个字符以后的所有字符,接下来求另一部分的排列,拿第一个字符和它后面的字符逐个交换。

class Solution {
public:
    vector<string> Permutation(string str) {
        if(str.size() != 0){
            char *pStr = &str[0];
            permutation(pStr,pStr);
            set<string>::iterator it = resultSet.begin();
            for(;it!=resultSet.end();it++)
                result.push_back(*it);
        }
        return result;
    }
    void permutation(char *pStr, char *pBegin){
        if(*pBegin == '\0')
            resultSet.insert(pStr);
        else
            for(char *pCh = pBegin; *pCh != '\0'; pCh++){
                char tmp = *pCh;
                *pCh = *pBegin;
                *pBegin = tmp;
                permutation(pStr, pBegin+1);
                tmp = *pCh;
                *pCh = *pBegin;
                *pBegin = tmp;
            }
    }
private:
    vector<string> result;
    set<string> resultSet;
};

面试题35:第一次只出现一次的字符
题目:在一个字符串(1<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置
解题思路:最直观的想法是扫描数组,把访问到的字符和后面所有字符比较,如果没有出现重复字符,就是答案,时间复杂度0(n2)。如果第一次扫描数组用一个hashTable保存每个字符出现的次数,第二次扫描再判断其次数是不是1,就可以把时间复杂度降为O(n)。

class Solution {
public:
    int FirstNotRepeatingChar(string str) {
        if(str == "")
            return -1;
        unsigned int hashTable[256];
        memset(hashTable,0,256*4);
        int len = str.length();
        for(int i=0; i<len; i++)
            hashTable[str[i]]++;
        for(int i=0;i<len;i++){
            if(hashTable[str[i]] == 1)
                return i;
        }
        return 0;
    }
};

面试题42:反转单次顺序 VS 左旋转字符串

题目:输入一个英文句子,反转句子中单词的顺序,但单词内字符的顺序不变。标点符号和普通字母一样处理。
解题思路:先反转整个句子,再反转每个单词。

class Solution {
public:
    string ReverseSentence(string str) {
        if(str == "")
            return "";
        int len = str.length();
        reverseCore(str,0,len-1);
        int start = 0,end = 0;
        while(start<len){
            if((str[end] == ' ')||(str[end] == '\0')){
                reverseCore(str,start,end-1);
                start = end+1;
            }
            end++;
        }
        return str;
    }
    void reverseCore(string &str, int start, int end){
        while(start<end){
            char tmp = str[start];
            str[start] = str[end];
            str[end] = tmp;
            start++;
            end--;
        }
    }
};

题目:字符串的坐旋转操作是把字符串前面的若干个字符转移到字符串的尾部。比如输入字符串“abcdefg”和数字2,返回左旋转2位得到的结果“cdefgab”。
解题思路:先把字符串整个反转。把字符串分成两部分,再分别反转。

class Solution {
public:
    string LeftRotateString(string str, int n) {
        if(str == "" || n < 1)
            return str;
        int len = str.length();
        reverseCore(str,0,len-1);
        n = n % len;
        reverseCore(str,0,len-1-n);
        reverseCore(str,len-n,len-1);
        return str;
    }
    void reverseCore(string &str, int start, int end){
        while(start<end){
            char tmp = str[start];
            str[start] = str[end];
            str[end] = tmp;
            start++;
            end--;
        }
    }
};

面试题54:表示数值的字符串

题目:请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串”+100”,”5e2”,”-123”,”3.1416”和”-1E-16”都表示数值。 但是”12e”,”1a3.14”,”1.2.3”,”+-5”和”12e+4.3”都不是。
解题思路:首先要分析能表示数值的字符串的pattern是什么样,[sign+-]integral-digits[.[fractional-digits]][e|E][sign+-][exponential-digits],[和]之间为可由可无的部分。

class Solution {
public:
    bool isNumeric(char* string)
    {
        if(string == NULL)
            return false;
        if(*string == '+' || *string == '-')
            string++;
        if(*string == '\0')
            return false;
        scanDigits(&string);
        bool numeric = true;
        if(*string != '\0'){
            if(*string == '.'){
                string++;
                scanDigits(&string);
                if(*string == 'e' || *string == 'E')
                    numeric = isExponential(&string);
            }else if(*string == 'e' || *string == 'E')
                numeric = isExponential(&string);
            else
                numeric = false;
        }
        return numeric && *string == '\0';
    }
    void scanDigits(char** string){
        while(**string != '\0' && **string >= '0' && **string <= '9')
            (*string)++;
    }
    bool isExponential(char** string){
        (*string)++;
        if(**string == '+' || **string == '-')
            (*string)++;
        if(**string == '\0')
            return false;
        scanDigits(string);
        return (**string == '\0') ? true : false;
    }
};

面试题55:字符流中第一个不重复的数字

题目:请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符”go”时,第一个只出现一次的字符是”g”。当从该字符流中读出前六个字符“google”时,第一个只出现一次的字符是”l”。如果当前字符流没有存在出现一次的字符,返回#字符。
解题思路:因为字符只能一个接一个从字符流中读出来。可以定义一个数据容器来保存字符在字符流中的位置。但是要高效向数据容器中插入以及更新字符对应的值,可以用哈希表来实现。

class Solution
{
public:
    Solution():index(0)
    {
        for(int i=0;i<256;i++)
            occurrence[i] = -1;
    }
  //Insert one char from stringstream
    void Insert(char ch)
    {
        if(occurrence[ch] == -1)
            occurrence[ch] = index;
        else if(occurrence[ch] >= 0)
            occurrence[ch] = -2;
        index++;
    }
  //return the first appearence once char in current stringstream
    char FirstAppearingOnce()
    {
        char ch = '#';
        int minIndex = INT_MAX;
        for(int i=0;i<256;i++){
            if(occurrence[i] >= 0 && occurrence[i] <= minIndex){
                minIndex = occurrence[i];
                ch = (char)i;
            }
        }
        return ch;
    }
private:
    int occurrence[256];
    int index;
};
阅读更多

没有更多推荐了,返回首页