致我们终将忘记的算法(千变万化字符串)

1->判断一个字符串是不是回文字符串,不考虑字符串的大小写和标点符号。例如:“A man,a plan,a canal:Panama”是一个回文串。而“race a car”则不是一个回文串

解题方法:没有什么特别的技巧,左右逐个比较久OK了,就是在代码的书写过程注意细节问题。

bool isPalindrome(string s){

    tranform(s.begin(),s.end(),s.begin(),::tolower);                           //将字符串转为小写的

    String::iterator left=s.begin(),right=s.end()--;

    while(left<right){

        if(!::isnalnum(*left))   left++;

        else if(!::isnalnum(*right))  right--;

        else if(*right!=*left)  return false;

    }

    return true;

}

2->字符串匹配算法

解题方法1:暴力匹配:时间复杂度O(M*N)  空间复杂度O(1)

char *strStr(char *haystack,char *needle){

    int len_h=strlen(haystack);

    int len_n=strlen(needle);

    if(len_h<len_n)   return NULL;

    else if(len_h==len_n){

        if(strcmp(haystack,needle))   return NULL;

        else return haystack;

    }

    for(int i=0;i<len_h-len_n;i++){

        bool flag=true;

        for(int j=0;j<len_n;j++){

               if(haystack[i+j]!=needle[j]){flag=false; break;}

        }

        if(flag) return haystack+i;

    }

    return NULL;

}

解题方法2:KMP算法:时间复杂度O(m+n),空间复杂度O(M)

void compute_prefix(const char *pattern,int next[]){

    const int m=strlen(pattern);

    int j=0;    next[1]=0;

    while(i<m){

        if(j==0 || pattern[i]==pattern[j]){++i;++j;next[i]=j;}

        else j=next[j];

    }

}

int Kmp(const char *text,const char *pattern){

    const int n=strlen(text);

    const int m=strlen(pattern);

    if(n==0&&m==0) return 0;

    if(m==0) return 0;

    int *next=(int *)malloc(sizeof(int)*m);

    comptue_prefix(pattern,next);

    int i=1,j=1;

    while(i<=m && j<=n){

        if(j==0||text[i]==pattern[j]){++i,++j}

        else j=next[j];

    }

    if(j>m) return i-m;

    else return 0;

}

3->将字符串转化为对应的整数,即实现atoi库函数的功能

解题方法:该题没有什么特别的技巧,要注意代码实现的细节,例如前导空格,+和-号问题,还有就是字符串中出现的非数字字符问题,要细致处理。

int atoi(const char *str){

    int num=0;

    int sign=1;

    const int n=strlen(str);

    int i=0;

    while(str[i]==' '&&i<n) i++;    //去掉前导空格

    if(str[i]='+') i++;

    else if(str[i]=='-'){ sign=-1;i++;}   //设置符号为减号

    for(;i<n;i++){

        if(str[i]<'0' || str[i]>'9') break;     //处理非数字符号问题

        if(num>INT_MAX/10 ||(num==INT_MAX/10  &&(str[i]-'0')>INT_MAX%10)){return sign==-1 ?INT_MIN:INT_MAX;}  //处理越界问题

        num=num*10+str[i]-'0';

    }

    return num*sign;

}

4->两个字符串表示的二进制数相加

String addBinary(string a,string b){

    string result;

    const int n=a.size()>b.size()?a.size():b.size();

    reverse(a.begin(),a.end());

    reverse(b.begin(),b.end());

    int carry=0;

    for(int i=0;i<n;i++){

         const int ai=i<a.size()?a[i]-'0':0;

         const int bi=i<b.size()?b[i]-'0':0;

         const int val=(ai+bi+carry)%2;

         carry=(ai+bi+carry)/2;

         result.insert(result.begin(),val+'0');

    }

    if(carry==1)  result.insert(result.begin(),'1');

    return result;

}


5->最长回文子串

解题方法:以源字符串的每个字符为中心,向左右扩展,求回文字符串的长度,(注意以字符为扩展中心,有两种情况,第一回文串的长度为偶数,和回文字符串的长度为奇数两种不同的情况。)

int Palindromic(const string& str,int i,int j){                                      //判断一个子字符串是否为回文字符串

    int n=str.size()  , curlen=0;

    while(i>=0  && j<n  &&str[i]==str[j]){

        i--;  j++;

    }

     curlen=(j-1)+(i+1)+1;

     return curlen;

}

string longestPalindrome(string s){

    int n=s.length();

    int startPos=0 ,maxlen=1;

    for(int i=0;i<n;i++){

        int oddlen=0, evenlen=0;

        int curlen=0;

        oddlen=Palindromic(s,i,i);

        if(i+1<n)    evenlen=Palindromic(s,i,i+1);

        if(curlrn>max){ 

            max=len;

            if(max &0x1)  startPos=i-max/2;

            else startPos=i-(max-1)/2; 

        }

    }

    return s.substr(startPos,max);

}


6->正则表达式字符串匹配问题,其中‘.’代表任意一个字符串,‘*’代表任意多个或者0个字符

解题方法:采用递归的方式,主要以当前字符的下一个字符是否为‘*’展开判断。

bool isMatch(const char *s,const char *p){

    if(*p=='\0') return s=='\0';

    if(*(p+1)!='*'){

        if(*p==*s || (*p=='.' && *s!='\0'))    return isMarch(s+1,p+1);

        else  return false;

    }else{

        while(*s==*p ||(*p=='.'  && *s!='\0')){

            if(isMatch(s,p+2))    return true;

            s++;

        }

        return isMatch(s,p+2);

    }

}


7->通配符字符串匹配(其中‘?’代表任意一个字符,‘*’代表任意多个或者0个序列)要求两个字符串要完全匹配

解题方法:递归版:

bool isMatch(const char *s,const char *p){

    if(s==NULL || p==NULL)    return false;

    if(*p=='\0')  return *s=='\0';

    if(*p=='*'){

        while(*p=='*') ++p;

        while(*s!='\0'){ if(isMatch(s,p))    return true;   s++;}

        return isMatch(s,p);

    }else{

         if((*s!='\0' && *p=='?') || *s==*p)  return isMatch(s+1,p+1);

    }

    return false;

}


8->求所有字符串的最长公共前缀

解题方法:

string longestCommonPrefix(vector<string> &strs){

    if(strs.empty())   return "";

    for(int idx=0;idx<str[0].size();idx++){

         for(int i=1;i<strs.size();i++){

               if(strs[i][idx]!=strs[0][idx]) return strs[0].substr(0,idx);

          }

    }

    return strs[0];

}


9->判断一个字符串是否可以转化为正确的浮点数

解题方法:调用标准库函数中的strtod来实现

bool isNumber(char const *s){

    char *endptr;

    strtod(s,&endptr);

    for(endptr==s)    return false;

    for(;*endptr;++endptr)

        if(!isspace(*endptr))    return false;

    return true;

}


10->将阿拉伯数字转化为罗马数字

string intToRoman(int num){

    const int radix[]={1000,900,500,400,90,50,40,10,9,5,4,1};

    const string symbol[]={"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};

    string roman;

    for(size_t i=0;num>0;i++){

        int count=num/radix[i];

        num%=radix[i];

        for(;count>0;--count) roman+=symbol[i];

    }

    return roman;

}


11->将罗马数字转化为阿拉伯数字

inline int map(const char c){

    switch(c){

        case 'I':return 1;

        case 'V':return 5;

        case 'X':return 10;

         case 'L':return 50;

         case ‘C’:return 100;

         case ‘D’:return 500;

         case ‘M’:return 1000;

         default:  return 0;

   }

    int romanToInt(string s){

         int result=0;

         for(int i=0;i<s.size();i++){

                if(i>0 &&map(s[i])>map(s[i-1])){

                     result+=(map(s[i])-2*map(s[i-1]));

                }else{

                    result+=map(s[i]);

                 }

         }

    }

      return result;

}


12->求出第n个countAndSay序列。其中countAndSay序列为:1->one 1->11   11->two 1->21

解题方法:安装题意即可完成

string getNext(const string &s){

    stringstream ss;

    for(string::iterator it=s.begin();it!=s.end();){

          auto j=find_if(it,s.end(),bind1st(not_equal_to<char>,*it));

           ss<<distance(it,j)<<*it;

           it=j'

    }

    return ss.str();

}

string countAndSay(int n){

    string s("1");

    while(--n){

         s=getNext(s);

    } 

    return s;   

}


13->返回一组单词中的所有回文构词法的单词

解题方法:回文构词法,只是将单词的顺序调换,所有如果两个单词有同样的一种排序,两个单词就是回文词

vector <string> anagrams(vector<string> &strs){

    map<string,vector<string>>  group;

    for(int i=0;i<strs.size(),i++){

        string key=strs[i];

        sort(key.begin(),key.end());

        group[key].push_back(s);

    }

    vector<string> result;

    for(vector<string>::it=group.begin();it!=group.end();it++){

         if(it->second.szie()>1)

                result.insert(result.end(),it->second.begin(),it->second.end());

         return result;

    }

}


14->求出一串句子的最后一个单词的长度

解题方法:调用string的库函数find_if  和find_if_not 可以确定最后一个单词的开始和结束位置,自然很容易求出最后一个单词的长度

int lengthOfLastWord(const char *s){

    const string str(s);

    auto first=find_if(str.rbegin(),str.rend(),::isalpha);

    auto last=find_if_not(first,str.rend(),::isalpha);

    return distance(first,last);

}


15->将一个复杂的文件路径转化为简单的文件路径(按照Linux文件路径访问方式)

解题方法:栈的方式

string simplifyPath(const string &path){

    vector<string> dirs;

    for(string::iterator it=path.begin();i!=path.end();){

         it++;

          string::iterator j=find(i,path.end(),'/');

          string dir=string(i,j);

          if(!dir.empty() && dir!='.'){

                  if(dir==".."){

                         if(!dirs.empty())  dirs.pop_back();

                  }

                  else  dirs.push_back(dir);

          }

          i=j;

    }

    stringstream out;

    if(dirs.empty()) out<<"/";

    else{

          for(auto dir:dirs) out<<'/'<<dir;

     }

     return out.str();

}

发布了99 篇原创文章 · 获赞 8 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/CodeAsWind/article/details/39084417
今日推荐