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();
}