程序员代码面试指南-字符串问题:C/C++语言实现
以下程序运行环境:VC6++
看到左老师出的书:程序员代码面试指南:IT名企算法与数据结构题目最优解,都是Java实现,为了刷题,但是职位是C/C++,以下是我用C/C++实现的代码 题目介绍略简单,以后补上/*
//程序员代码面试指南-字符串问题
//1.判断两个字符串是否互为变形词bool isDeformation(string str1,string str2){if(str1.length() !=str1.length())return false;const char *chas1=str1.c_str();const char *chas2=str2.c_str();int *map = new int[256];//字符的ASC在0-255之间for(int i=0;i<str1.length();i++)map[chas1[i]]++;//字符对应的asc码值所在的数组数值++for(int j=0;j<str2.length();j++)if(map[chas2[j]]-- == 0)//先判断再--return false;return true;}int main(){string str1,str2;getline(cin,str1);getline(cin,str2);(isDeformation(str1,str2)==true)? cout<<"yes\n" : cout<<"no\n" ;return 0;}
*/
/*
//2.字符串中数字子串的求和:给定一个字符串,求其中全部数字串所代表的数字之和
//eg:a1cd-2ef33 ==1-2+33=21
int numSum(string str){const char *str1=str.c_str();int num=0;//提取出的当前数字int sum=0;//最后的和int cur=0;//当前数值bool posi=true;for(int i=0;i<str.length();i++){cur=str1[i]-'0';//转换为数字if(cur<0 || cur>9)//不是数字{sum+=num;//不是数字后计算和num=0;if(str1[i] == '-'){if(i-1>-1 && str1[i-1]=='-')//如果前一个也是-则取反posi=!posi;elseposi=false;}else posi=true;//+}else{num=num*10+((posi)? cur : -cur );}}sum+=num;//当最后一个字符是数字的话在这里加上,因为sum是在不为数字时候计算的return sum;}int main(){string str;getline(cin,str);cout<<numSum(str);}
*/
/*
//3.去掉字符串中连续出现K个0的子串
string removeKZeros(string str,int k){char *str1=new char[str.length()];strcpy(str1,str.c_str());int start=-1,count=0;for(int i=0;i<str.length();i++){if(str1[i]=='0'){count++;start=((start==-1)? i:start);}else{if(count==k)while(count--!=0)str1[start++]=0;count=0;start=-1;}}if(count==k)//如果最后一个字符是0的情况while(count--!=0)str1[start++]=0;return str=str1;}int main(){string str;int k;cin>>k;cin.ignore();//不忽略剩余的回车会导致getline无效getline(cin,str);//输入两个回车是因为VC6的bugcout<<removeKZeros(str,3);return 0;}
*/
/*
//4.判断两个字符串是否互为旋转词:思路:在b+b中看是否包含a
bool isRotation(string a,string b){if(a.length()!=b.length())return false;string b2=b+b;return strstr(b2.c_str(),a.c_str())!=NULL;}int main(){string a,b;getline(cin,a);getline(cin,b);isRotation(a,b)? cout<<"yes"<<endl : cout<<"no"<<endl;return 0;}
*/
/*
//5.将整数字符串转成整数值:符合日常形式eg"012"不符合,32位不能溢出
//判断是否符合日常形式函数
bool isValid(const char chas[],int len){if(chas[0] !='-' && (chas[0]<'0' || chas[0]>'9'))//首位不是-和数字不符合return false;if(chas[0]=='-' && (len==1 || chas[1]=='0'))return false;if(chas[0]=='0' && len>1)return false;for(int i=0;i<len;i++)if(chas[i]<'0' || chas[i]>'9')return false;return true;}//转换函数int convert(string str){const char* chas=str.c_str();if(isValid(chas,str.length())!=true)//不符合return 0;bool posi= chas[0]=='-'? false:true;int minq=-(2147483648/10);//下面计算中如果还小于此数就是溢出了int minr=-(2147483648%10);//如果等于上数后且余数小于次数就是溢出了,因为都是负数所以才是小于int res=0;int cur=0;for(int i=0;i<str.length();i++){cur='0'-chas[i];//负数if(res<minq || (res==minq && cur<minr))return 0;res=res*10+cur;}if(posi && res==-2147483648)//整数最大是2147483647return 0;return posi? -res:res;}int main(){string str;getline(cin,str);cout<<convert(str);return 0;}
*/
/*
//6.替换字符串,将str中from替换为to eg:str=123abc from=abc to=4567 返回1234567 str=123abcabc from=abc to=x 返回123x:只有一个x注意
//想法:将原字符串中from字符替换为0,然后碰到0的地方str相加
string replace(string str,string from,string to){char *str1=new char[str.length()+1];strcpy(str1,str.c_str());const char *from1=from.c_str();int match=0;for(int i=0;i<str.length();i++)//查找from后添0{if(str1[i]==from1[match++]){if(match==from.length())//是fromwhile(match){str1[i-match+1]=0;;match--;}}else{match=0;}}string res="";string cur="";for(int j=0;j<str.length();j++)//在0的地方补to{if(str1[j]!=0)cur+=str1[j];//一个个的排起来if(str1[j]==0 && (j==0 || str1[j-1]!=0)){res+=cur+to;cur="";}}if(cur.c_str()!="")res+=cur;//最后一部分delete[] str1;return res;}int main(){string str,from,to;getline(cin,str);getline(cin,from);getline(cin,to);cout<<replace(str,from,to);return 0;}
*/
/*
//7.统计字符串eg:aaabbadddffc a_3_b_2_a_1_d_3_f_2_c_1
#include <sstream>//字符串流,作字符串int转换用的string getCountString(string str){const char *str1=str.c_str();string res="";res+=str1[0];//char转string直接赋值stringstream ss;string tmp;int num=1;for(int i=1;i<str.length();i++){if(str1[i]!=str1[i-1]){ss.clear();ss<<num;//int转字符串ss>>tmp;res+="_"+tmp+"_"+str1[i];num=1;}elsenum++;}ss.clear();ss<<num;ss>>tmp;return res+="_"+tmp;}int main(){string str;getline(cin,str);cout<<getCountString(str);return 0;}
*/
/*
//8.给定一个index返回上题统计字符串中第index个原始字符eg:a_1_b_100 index=50 返回b
char getCharAt(string str,int index){const char *str1=str.c_str();bool stage=true;//当前在遍历字符还是数字标志,true字符int num=0,sum=0;char cur;for(int i=0;i<str.length();i++){if(str1[i]=='_')stage=!stage;else if(stage){sum+=num;if(sum>index)return cur;num=0;cur=str1[i];}else num=num*10+str1[i]-'0';}return sum+num>index ? cur:0;}int main(){string str;int index;cin>>index;cin.ignore();getline(cin,str);cout<<getCharAt(str,index);return 0;}
*/
/*
//9.判断字符数组中是否所有的字符都只出现过一次,未规定空间复杂度
bool isUniquel(const char *buf,int len){bool map[256]={0};for(int i=0;i<len;i++){if(map[buf[i]]){cout<<map[buf[i]];return false;}map[buf[i]]=true;}return true;}int main(){string str;getline(cin,str);isUniquel(str.c_str(),str.length())==true ? cout<<"true" : cout<<"false";return 0;}
*/
/*
//10.上题中要求空间复杂度为O(1)时间复杂度尽量低
//思路:排序后查找是否大于1,关键在与排序算法的选择,堆排序 O(1)空间,时间O(nlogn)
void HeapAdjust(char a[],int s,int n){//调整为小根堆,从小到大int rc=a[s];for(int j=2*s;j<=n;j*=2){if(j<n && a[j]>a[j+1])//判断左右子数大小j++;if(rc<=a[j])break;a[s]=a[j];s=j;}a[s]=rc;}//第一步:建初堆void CreatHeap(char a[],int n){//小根堆for(int i=n/2;i>0;i--)HeapAdjust(a,i,n);}//整合void HeapSort(char a[],int n){CreatHeap(a,n);//第一步,建立初堆for(int i=n;i>1;i--){int x=a[1];//堆顶与最后一个元素互换a[1]=a[i];a[i]=x;HeapAdjust(a,1,i-1);}}//查找方法bool isUnique2(char a[],int n){//调用排序算法HeapSort(a,n);for(int i=1;i<n;i++)if(a[i]==a[i-1])return false;return true;}int main(){string str;getline(cin,str);char *a=new char[str.length()+1];strcpy(a,str.c_str());cout<<(isUnique2(a,str.length())==true ? "true":"false");delete[] a;return 0;}
*/
/*
//11.在从小到大排序但含有null的字符串中查找字符串出现的位置,eg:{a,null,b,c,null,d,c..}中查找c出现最左的位置3
//思路:二分查找,因为是已经有序的了
//下面程序其实不对了:下面意思是从排序但含有空格的字符串中查找字符出现的位置 (空格和NULL不是一回事,空格是' 'asc=32,null是指针其值为0,结束符是'\0'ASC=0)
//所以真正的程序这里应该用字符串数组
int getIndex(string str,char c){int res=-1;int left=0;int right=str.length()-1;int mid=0;int i=0;const char *buf=str.c_str();while(left<=right){mid=(left+right)/2;if(buf[mid]!=' '){if(buf[mid]==c)//正好就是,不一定是最左,还要在左侧找{res=mid;right=mid-1;}else if(buf[mid]<c)//在右侧left=mid+1;else right=mid-1; //在左侧}else {i=mid;while(str[i]==' ' && --i>=left);//依次向左找if(i<left || str[i]<c)//如果左侧都是空或者左侧中的最右一个非空字符<c,则从右侧找left=mid+1;else //在左侧中{res=(str[i]==c? i:res);right=i-1;}}}return res;}int main(){string str;char c;getline(cin,str);cin>>c;cout<<getIndex(str,c);return 0;}
*/
/*
//11.1字符串调整与替换:将空格替换为%20,注意空格是一字节,%20是三字节,数组不能越界
//思路:遍历一遍,看看数组中有多少个字符,多少个空格,然后重新计算替换后的数组长度,从右向左替换转换位置
void replace(char buf[]){int len=0;//buf多少字符int num=0;//空格个数int size=0;//替换后长度for(len=0;buf[len]!='\0';len++)if(buf[len]==' ')num++;size=len+2*num-1;for(int i=len-1;i>=0;i--){if(buf[i]!=' ')buf[size--]=buf[i];else {buf[size--]='0';buf[size--]='2';buf[size--]='%';}}}int main(){string str;getline(cin,str);char *buf=new char[256];//这里用定长表示的足够大strcpy(buf,str.c_str());replace(buf);cout<<buf;delete[] buf;return 0;}
*/
/*
//11.2字符串调整与替换:字符只有数字和*,将所有*移到数字左侧,且不能改变数字之前顺序eg12**45 **1245
//思路:从右往左遍历,是数字就从右到左放,不怕将*覆盖了,没有数字了后将剩下的区域全部复制成*就好了,因为不是数字就是*
void modify(char buf[],int len){int j=len-1;for(int i=j;i>=0;i--){if(buf[i]!='*')buf[j--]=buf[i];}while(j>=0)buf[j--]='*';}int main(){string str;getline(cin,str);char *buf=new char[str.length()+1];strcpy(buf,str.c_str());modify(buf,str.length());cout<<buf;delete[] buf;return 0;}
*/