字元的左右移動
題目 字串是任意的*和字母的組合,設計演算法,把*都移到最左邊,字母都移到最右邊且保持相對順序不變。
實現 逆序處理字串。雙指標,一個指標alpha最初指向最右邊的字元,另一個last指標最初指向最右邊的*。 當alpha指向字母時,就和last指向的字元互換,並且這兩個指標同時向左移一位。 當alpha指向*時,只有alpha向左移動一位。 當alpha<0時,結束。
代碼
void change(string& s){ int len = s.length(); int alpha = len - 1; //找到最右邊的字母 while (alpha>=0&&s[alpha] == '*') alpha--; int last = len - 1; while (alpha >= 0) { if (s[alpha] != '*') { swap(s[alpha--], s[last--]); } else alpha--; }}
字串的匹配
題意 支援.和*的Regex匹配。 .匹配任一字元,*匹配0個或多個前面的字元。 字串p是匹配模式,s是要匹配的字串。
實現 遞迴,從後往前比較。 i,j分別是s和p當前考慮的字元的位置,初值分別為slen-1和plen-1. 按照p[j]是.,*還是字元分情況考慮:
當p[j]=‘.’時,若(s,i-1,p,j-1)匹配返回了true,則(s,i,p,j)返回true。 當p[j]=‘*’時,若(s,i-1,p,j-2)匹配返回了true,則(s,i,p,j)返回true;否則依次從後往前遍曆剩下的s字元,如果遍曆到s下標為k的字元滿足s[k]==p[j-1]或者p[j]==‘.’,則當(s,k-1,p,j-2)返回true時,(s,i,p,j)也返回true。 當p[j]是其他字元時,只有當s[i]==p[j]而且(s,i-1,p,j-1)返回true時,(s,i,p,j)才返回true。
代碼
bool isMatch(string &s,string &p){ return help(s,s.length()-1,p,p.length()-1);}bool help(string &s,int i,string &p,int j){ //特殊情況處理:若p的長度為0,只有當s的長度也為0時才返回true if(j==-1) return i==-1; if(p[j]=='.') return i>=0&&help(s,i-1,p,j-1); if(p[j]=='*') { if(help(s,i-1,p,j-2)) return true; for(int k=i;k>=0;k--) { //‘*’依次匹配1個,2個,3個,...相同的前字元p[j-1], //直到s[k]與p[j-1]不匹配為止。 if(s[k]==p[j-1]||p[j-1]=='.') { if(help(s,k-1,p,j-2)) return true; } else return false; } } else { if(i>=0&&help(s,i-1,p,j-1)) return true; } return false;}
字串空格壓縮
題意 將字串中連續出現的空格壓縮成一個並將以空格分開的字串逆序列印出來。
實現 istringstream:用於處理行內對每個單詞。
#
void reverse(string &s){ int len=s.length(); if(len<=1) return; for(int i=0;i<len/2;i++) { swap(s[i],s[len-i-1]; }}void comp(string &s){ istringstream is(s); string word; s.clear(); while(is>>word) { reverse(word); s=s+word+' '; } s.pop_back();}
重複字元的壓縮
題意 對字串中重複出現的字母進行壓縮,按要求輸出壓縮後的字串。 比如字串xxyyyyyz,壓縮後為2x5yz,其中z只出現一次故不壓縮。
實現 遍曆啊遍曆
代碼
//將int轉換成字串string num2str(int n){ string ans; if(n==0) return "0"; while(n) { char tmp='0'+n%10; n/=10; ans=tmp+ans; } return ans;}string dup(string &s){ int count=1; string ans; for(int i=1;i<s.length();i++) { if(s[i]==s[i-1]) count++; else { if(count==1) ans+=s[i]; else ans=ans+num2str(count)+s[i]; count=1; } } if(count==1) ans+=s[i]; else ans=ans+num2str(count)+s[i]; return ans;}
第一個只出現一次的字元
題意 在一個字串中找出第一個只出現一次的字元。 比如輸入abaccdeff,輸出b
實現 笨辦法:在字元和出現的下標建立映射。 沒有這個字元則加進去,否者讓這個字元對應的下標設為-1.
代碼
//假定這個出現僅一次的字元一定存在char OnlyFirst(string &s){ if(s.length()==1) return s[0]; map<char,int>mp; for(int i=0;i<s.length();i++) { if(mp.count(s[i])) mp[s[i]]=-1; else mp[s[i]]=i; } int minIndex=s.length(); for(auto iter=map.begin();ier!=map.end();iter++) { if(iter->second!=-1) { if(iter->second<minIndex) minIndex=iter->second; } } return s[minindex];}
誰有更好的方法。。 刪除特定的字元 題意 給定原始字元s和模式字串p,要求在原始字元中刪除所有在模式字串中出現過的字元。 實現 在原始字串中,把出現在模式字串中的字元用後面的字元覆蓋上來。在匹配完後,原始字串最後一個字元後面賦值為'\0'即可。 string是順序儲存結構,每刪除一個字元,後面的字元都要一個個移動到前面來,這樣時間複雜度很高。 代碼
void deleteString(string &s,string &p){ int slen=s.length(); int plen=p.length(); if(slen==0||plen==0) return; int hash[256]={0}; for(int i=0;i<plen;i++) hash[p[i]]=1; int slow=0; int fast=0; while(fast!=slen) { if(hash[s[fast]]!=1) { s[slow++]=s[fast]; } fast++; } s=s.substr(0,slow);}