牛客网剑指offer字符串题目总结(共10道)

牛客网剑指offer字符串题目总结(共10道)

1、替换空格(剑指2)

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

解题思路:先计算加了空格的总长度,然后从后往前复制。

class Solution {
public:
	void replaceSpace(char *str,int length) {
        int i,len=0;
        for(i=0;i<length;i++)
            if(str[i]==' ') len++;
        int j=length+len*2-1;
        i=length-1;
        while(i>=0){
            if(i==j) break;
            if(str[i]!=' ')
                str[j--]=str[i--];
            else{
                str[j--]='0';
                str[j--]='2';
                str[j--]='%';
                i--;
            }
        }
	}
};

2、字符串的排列(剑指27)

输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。

输入描述:输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。

思路:递归法,问题转换为先固定第一个字符,求剩余字符的排列;求剩余字符排列时跟原问题一样。

(1) 遍历出所有可能出现在第一个位置的字符(即:依次将第一个字符同后面所有字符交换);

(2) 固定第一个字符,求后面字符的排列(即:在第1步的遍历过程中,插入递归进行实现)。
需要注意的几点:

先确定递归结束的条件,例如本题中可设begin == str.size() - 1;

形如 aba 或 aa 等特殊测试用例的情况,vector在进行push_back时是不考虑重复情况的,需要自行控制;

(3) 输出的排列可能不是按字典顺序排列的,可能导致无法完全通过测试用例,考虑输出前排序,或者递归之后取消复位操作

class Solution {
public:
    vector<string> Permutation(string str) {
        vector<string> result;
        Permutation(str,result,0);
        sort(result.begin(),result.end());
        return result;
    }
    void Permutation(string str,vector<string> &result,int begin){
        if(begin==str.size()-1){
            if(find(result.begin(),result.end(),str)==result.end()){
                result.push_back(str);
                return;
            }
        }
        else{
            for(int i=0;i<str.size();i++){
                swap(str[begin],str[i]);
                Permutation(str,result,begin+1);
                swap(str[begin],str[i]);
            }
        }
    }
    void swap(char &a,char &b){
        char c=a;
        a=b;
        b=c;
    }
};

3、第一个只出现一次的字符(剑指34,简单题)

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

class Solution {
public:
    int FirstNotRepeatingChar(string str) {
        map <char,int> s;
        for(int i=0;i<str.size();i++){
            s[str[i]]++;
        }
        for(int i=0;i<str.size();i++){
            if(s[str[i]]==1) return i;
        }
        return -1;
    }
};

4、左旋转字符串(剑指43)

汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。是不是很简单?OK,搞定它!

class Solution {
public:
    string LeftRotateString(string str, int n) {
        int len=str.size(),i,j;
        if(len<=0) return "";
        n%=len;
        str+=str;
        return str.substr(n,len);
        
    }
};

5、翻转单词顺序列(剑指44)

牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思。例如,“student. a am I”。后来才意识到,这家伙原来把句子单词的顺序翻转了,正确的句子应该是“I am a student.”。Cat对一一的翻转这些单词顺序可不在行,你能帮助他么?

class Solution {
public:
    //先翻转整个句子,再一次翻转每个单词,最后一个单词单独翻转。
    string ReverseSentence(string str) {
        reverse(str.begin(),str.end());
        int begin=0;
        int i=0;
        while(str[i]==' ') i++;
        for(;i<str.size();i++){
            if(str[i]==' '){
                reverse(str.begin()+begin,str.begin()+i);
                begin=i+1;
            }
        }
        reverse(str.begin()+begin,str.end());
        return str;
    }
};

6、扑克牌顺子(剑指45)

LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张_)...他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决定去买体育彩票,嘿嘿!!“红心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是顺子.....LL不高兴了,他想了想,决定大\小王可以看成任何数字,并且A看作1,J为11,Q为12,K为13。上面的5张牌就可以变成“1,2,3,4,5”(大小王分别看作2和4),“So Lucky!”。LL决定去买体育彩票啦。 现在,要求你使用这幅牌模拟上面的过程,然后告诉我们LL的运气如何, 如果牌能组成顺子就输出true,否则就输出false。为了方便起见,你可以认为大小王是0。

class Solution {
public:
//必须满足  数组包含5个数 除0外没有重复的数 max - min < 5
    bool IsContinuous( vector<int> numbers ) {
        int len=numbers.size();
        if(len!=5) return false;
        sort(numbers.begin(),numbers.end());
        int i=0;
        while(numbers[i]==0) i++;
        if(numbers[len-1]-numbers[i]>4) return false;
        for(;i<len-1;i++)
            if(numbers[i]==numbers[i+1]) return false;
        return true;      
    }
};

7、把字符串转换为整数(剑指49)

将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0

class Solution {
public:
    int StrToInt(string str) {
        int flag=1;
        long long sum=0;
        int i=0;
        if(str[0]=='+') i++;
        else  if(str[0]=='-') {i++;flag=-1;}
        for(;i<str.size();i++){
            while(str[i]=='0') i++;
            if(str[i]>='0'&&str[i]<='9') sum=sum*10+str[i]-'0';
            else return 0;
        }
        if(flag==1&&sum>INT_MAX) return 0;
        if(flag==-1&&(-1)*sum<INT_MIN) return 0;
        return (int)(sum*flag);
    }
};

8、正则表达式匹配(剑指52)

请实现一个函数用来匹配包括'.'和'*'的正则表达式。模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但是与"aa.a"和"ab*a"均不匹配

方法一:递归方法:

class Solution {
public:
    bool match(char* str, char* pattern)
    {
        if(*str=='\0'&&*pattern=='\0') return true;
        if(*str!='\0'&&*pattern=='\0') return false;
        if(*(pattern+1)!='*'){
            if(*str==*pattern||(*str!='\0'&&*pattern=='.'))
                return match(str+1,pattern+1);
            else return false;
        }
        else{
            if(*pattern==*str||(*str!='\0'&&*pattern=='.'))
                return match(str,pattern+2)||match(str+1,pattern);
            else return match(str,pattern+2);
        }
        return false;
    }
};

方法二:动态规划

class Solution {
public:
    bool match(char* str, char* pattern)
    {
        int len1=strlen(str),len2=strlen(pattern);
        vector<vector<bool>> dp(len1+1,vector<bool>(len2+1,false));
        dp[len1][len2]=true;
        int i,j;
        for(i=len1;i>=0;i--){
            for(j=len2-1;j>=0;j--){
                if(j<len2-1&&pattern[j+1]=='*'){
                    if(i<len1&&(str[i]==pattern[j]||pattern[j]=='.')) dp[i][j]=dp[i][j+2]||dp[i+1][j];
                    else dp[i][j]=dp[i][j+2];
                }
                else{
                    if(i<len1&&(str[i]==pattern[j]||pattern[j]=='.')) dp[i][j]=dp[i+1][j+1];
                }
            }
        }
        return dp[0][0];
    }
};

9、表示数值的字符串(剑指53)

class Solution {
public:
    bool isNumeric(char* string)
    {
        bool sign=false,decimal=false,flag=false;
        for(int i=0;i<strlen(string);i++){
            if(string[i]=='e'||string[i]=='E'){
                if(i==0||sign) return false;
                if(i==strlen(string)-1) return false;
                sign=true;
            }
            else if(string[i]=='+'||string[i]=='-'){
                if(flag&&string[i-1]!='e'&&string[i-1]!='E') return false;
                if(!flag&&i>0&&string[i-1]!='e'&&string[i-1]!='E') return false;
                flag=true;
            }
            else if(string[i]=='.'){
                if(decimal||sign) return false;
                if(i==0) return false;
                decimal=true;
            }
            else if(string[i]<'0'||string[i]>'9') return false;
        }
        return true;
    }
  
};

10、字符流中第一个不重复的字符(剑指54)

请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"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++)
            m[s[i]]++;
        for(int i=0;i<s.size();i++)
            if(m[s[i]]==1) return s[i];
        return '#';
    
    }
    vector <int> s;
};
posted @ 2020-07-01 01:16  拉里拉里啦啦  阅读(122)  评论(0编辑  收藏  举报