Chaptert1--Arrays_and_Strings

来源:互联网 发布:淘宝1万多的充气娃娃 编辑:程序博客网 时间:2024/04/29 22:17

1.1Implement an algorithm to determine if a string has all unique characters. What if you can not use additional data structures?

即:实现一个算法来判断一个字符串中所有的字符是否都是唯一的(没有重复字符)。如果你不能使用额外的数据结构。

        作为简化,假设字符集是ASCII(如果不是,我们需要增加存储空间,其余的逻辑都是一样的)。注意:如果把这个问题指出给面试官将会是很出彩的表现。

#include<iostream>#include<string>#include<stdlib.h>#include<algorithm>#include<memory.h>using namespace std;//时间复杂度是O(n),空间复杂度是O(n)bool isUniqueChars1(string str){bool char_set[256];memset(char_set,0,sizeof(char_set));for(int i=0;i<str.length();i++){int val=(int)str[i];   //把char类型转换成为int类型,用val来指示相应字符的ASCII码if(char_set[val])  return false;   //如果所对应的字符存在,即有相同字符,那么返回falsechar_set[val]=true;       //如果相应字符第一次出现,那么将其标记为true}return true;                //遍历所有字符都没有重复,则返回true}//时间复杂度为O(n),我们还可以通过位运算来减少空间的使用量。 用每一位表征相应位置字符的出现。//对于ASCII字符,我们需要256位,即一个长度为8的int 数组a即可。这里的关键是要把字符对应的数字,//映射到正确的位上去。比如字符'b'对应的代码是98,那么我们应该将数组中的哪一位置为1呢?//用98除以32,得到对应数组a的下标: 3。98对32取模得到相应的位:2bool isUniqueChars2(string str){int a[8];for(int i=0;i<str.length();i++){int val=(int)str[i];int row=val/32,col=val%32;if(a[row]&(1<<col))  return false;  //将1相左移动col位a[row] |= (1<<col);}return true;}//情况与2类似,但是有一个限制就是字符str[i]与'a'的距离不能太大以至于超过32,因为int checker最多32bit//太大会造成移位越界bool isUniqueChars3(string str){int checker=0;for(int i=0;i<str.length();i++){int val=(int)(str[i]-'a');if(checker & (1<<val))   return false;checker |= (1<<val);}return true;}//时间复杂度O(n^2),空间复杂度为零,暴力匹配,时间复杂度最低bool isUniqueChars4(string str){for(int i=0;i<str.length();i++){for(int j=i+1;j<str.length();j++){if(str[i]==str[j])  return false;}}return true;}//排序的时间复杂度为O(nlogn),遍历数组时间复杂度O(n)bool isUniqueChars5(string str){sort(str.begin(),str.end());       //调用sort对str进行排序for(int i=0;i<str.length()-1;i++){if(str[i]==str[i+1]) return false;}return true;}int main(){string str1="I come from China.";string str2="abcdefghijklmnopqrstuvwxyz";cout<<"Case 1 : "<<isUniqueChars1(str1)<<","<<isUniqueChars1(str2)<<endl;cout<<"Case 2 : "<<isUniqueChars2(str1)<<","<<isUniqueChars2(str2)<<endl;cout<<"Case 3 : "<<isUniqueChars3(str1)<<","<<isUniqueChars3(str2)<<endl;cout<<"Case 4 : "<<isUniqueChars4(str1)<<","<<isUniqueChars4(str2)<<endl;cout<<"Case 5 : "<<isUniqueChars5(str1)<<","<<isUniqueChars5(str2)<<endl;return 0;}
运行结果:



1.2:Write code to reverse a C-Style String. (C-String means that “abcd” is represented as five characters, including the null character.)

即:写一段代码来转置C-类型的字符串.(C类型的字符串说明"abcd"代表五个字符,其中包括空字符.)

代码:

#include<iostream>#include<string.h>using namespace std;void reverse1(char *str){char *p=str;if(str)      //如果str!=NULL则继续{while(*p)   //直到*p为空字符p++;}p--;        //跳过空字符char tmp;while(str<p) //指针str从左向右移动,指针p从右向左移动{tmp=*str;*str++=*p;*p--=tmp;}}//代码相对于reverse1更简洁voidreverse2(char* str){char tmp;for(int i=0,j=strlen(str)-1 ; i<j ; i++,j--){tmp=str[i];str[i]=str[j];str[j]=tmp;}}int main(){char str1[]="abcdefghijklmnopqrstuvwxyz";char str2[]="ABCDEFGHIJKLMNOPQRSTUVWXYZ";reverse1(str1);cout<<"str1 : "<<str1<<endl;reverse2(str2);cout<<"str2 : "<<str2<<endl;return 0;}
运行:



1.3:Design an algorithm and write code to remove the duplicate characters in a string without using any additional buffer. NOTE: One or two additional variables are fine. An extra copy of the array is not.
FOLLOW UP Write the test cases for this method.

即:设计一个算法来写出代码去除一个字符串中重复的字符,不能使用任何额外的数组。注意:一个或者两个变量时可以的,但是整个数组的拷贝时不能接受的。

测试用例:

1).不包含任何重复字符,例如:abcde

2).全都是重复字符,例如:aaaa

3).空字符

4).连续重复的字符,例如:aaabbb

5).不连续重复的字符,例如:abababa

代码:

#include<iostream>#include<string.h>#include<memory.h>using namespace std;//时间复杂度为O(n^2),有点像是尾插法,第i(2,3,...,n)个元素,依次和前tail个各不相同的元素比较,//没有匹配的,那么插入尾部。void rmDumplicate0(char* str){if(str==NULL)  return ;int len=strlen(str);if(len<2)  return ;int i,j;int tail=1;for(i=1;i<len;i++)    //遍历所有元素{for(j=0;j<tail;j++)    //判断str[i]和前tail项是否有匹配{if(str[j]==str[i])  break;}if(j==tail)            //如果没有匹配的那么就插入尾部            {str[tail]=str[i];tail++;}}str[tail]='\0';}//时间复杂度为O(n^2),和rmDumplicate1相反,这是把每个元素和后面的元素相比较,如果相同就替换为//空格void rmDumplicate1(char* str){if(str==NULL)  return ;int len=strlen(str);if(len<2) return ;for(int i=0;i<len-1;i++){for(int j=i+1;j<len;j++){if(str[i]==str[j])        {str[j]=' ';}}}}//时间复杂度为O(n),假设输入的字符为ASCII码,那么就可以把每个元素映射到一个布尔类型长度为256的数组中去void rmDumplicate2(char* str){if(str==NULL) return ;int len=strlen(str);if(len<2)  return ;bool hit[256];memset(hit,0,sizeof(hit));hit[str[0]]=true;int tail=1;for(int i=1;i<len;i++){if(hit[str[i]]==false)   {str[tail++]=str[i];hit[str[i]]=true;     //把出现过的字符映射设置为true}}str[tail]='\0';}//假设输入的字符为'a'--'z'的情况下,算法的时间复杂度为O(n),定义一个int类型的变量,可以表示32位,通过//void rmDumplicate3(char* str){if(str==NULL)  return ;int len=strlen(str);if(len<2) return ;int checker=0,tail=0;for(int i=0;i<len;i++){int val=(int)(str[i]-'a');if( ( checker & (1<<val) ) == 0 ){str[tail++]=str[i];checker |= (1<<val);}}str[tail]='\0';}int main(){char s1[][10]={"abcde","abcde","abcde","abcde"};char s2[][10]={"aaabbb","aaabbb","aaabbb","aaabbb"};char s3[][10]={"","","",""};char s4[][10]={"abababa","abababa","abababa","abababa"};char s5[][10]={"aaaa","aaaa","aaaa","aaaa"};/*对数组s1进行操作*/
        cout<<"Case 1 :"<<endl;
rmDumplicate0(s1[0]);cout<<s1[0]<<endl;rmDumplicate1(s1[1]);cout<<s1[1]<<endl;rmDumplicate2(s1[2]);cout<<s1[2]<<endl;rmDumplicate3(s1[3]);cout<<s1[3]<<endl;/*对数组s2进行操作*/
        cout<<"Case 2 :"<<endl;rmDumplicate0(s2[0]);cout<<s2[0]<<endl;rmDumplicate1(s2[1]);cout<<s2[1]<<endl;rmDumplicate2(s2[2]);cout<<s2[2]<<endl;rmDumplicate3(s2[3]);cout<<s2[3]<<endl;/*对数组s3进行操作*/
        cout<<"Case 3 :"<<endl;rmDumplicate0(s3[0]);cout<<s3[0]<<endl;rmDumplicate1(s3[1]);cout<<s3[1]<<endl;rmDumplicate2(s3[2]);cout<<s3[2]<<endl;rmDumplicate3(s3[3]);cout<<s3[3]<<endl;/*对数组s4进行操作*/
        cout<<"Case 4 :"<<endl;rmDumplicate0(s4[0]);cout<<s4[0]<<endl;rmDumplicate1(s4[1]);cout<<s4[1]<<endl;rmDumplicate2(s4[2]);cout<<s4[2]<<endl;rmDumplicate3(s4[3]);cout<<s4[3]<<endl;/*对数组s5进行操作*/
        cout<<"Case 5 :"<<endl;rmDumplicate0(s5[0]);cout<<s5[0]<<endl;rmDumplicate1(s5[1]);cout<<s5[1]<<endl;rmDumplicate2(s5[2]);cout<<s5[2]<<endl;rmDumplicate3(s5[3]);cout<<s5[3]<<endl;return 0;}
运行结果:




1.4:Write a method to decide if two strings are anagrams or not.

即:写一个函数来判断两个字符串是否是变位词。所谓的变位词就是指两个字符串的组成字符一样,但是字符的顺序可能会不一致。

算法1:时间复杂度为O(n).去检测两个字符串中每个独立的字符是否具有相同的个数。

算法2:时间复杂度为O(nlogn).首先对字符串进行排序,然后再进行比对。

通过代码进行分析:

#include<iostream>#include<string.h>#include<memory.h>#include<stdlib.h>#include<algorithm>using namespace std;//算法1:时间复杂度为O(n).去检测两个字符串中每个独立的字符是否具有相同的个数。bool IsAnagram1(string s,string t){if(s.length()!=t.length()) return false;//如果两个字符串长度不同,一定不会是变位词int len = s.length();int flag[256]={0} , i;memset(flag,0,sizeof(flag));int num_unique_chars=0;    //互不相同的字符的个数int num_completed_t=0;for(i=0;i<len;i++)      //对字符串s进行处理{int loc=(int)s[i];  //得到每个字符s[i]的ASCII码,将他们映射到数组flag中,并统计同一字符出现的频次if(flag[loc]==0) ++num_unique_chars;++flag[loc];}for(i=0;i<len;i++)      //对字符串t进行处理{int loc=(int)t[i];if(flag[loc]==0)  return false;--flag[loc];if(flag[loc]==0){++num_completed_t;if(num_unique_chars == num_completed_t){return (i == len-1)?true:false;}}}return false;}//算法2:时间复杂度为O(nlogn).首先对字符串进行排序,然后再进行比对。bool IsAnagram2(string s,string t){if( s.length()!=t.length() ) return false;//如果两个字符串长度不同,一定不会是变位词sort(s.begin(),s.end());    //对s进行排序sort(t.begin(),t.end());    //对t进行排序return ( s==t ) ? true:false;    //如果相同则说明是变位词,否则不是}int main(){/*测试用例*/string s="abcde";string t="edcba";string s1="abcabcabc";string t1="cbacbacba";string s2="aaabbb";string t2="bbbccc";if(IsAnagram1(s,t))  cout<<"IsAnagram"<<endl;else cout<<"IsNotAnagram"<<endl;if(IsAnagram1(s1,t1))  cout<<"IsAnagram"<<endl;else cout<<"IsNotAnagram"<<endl;if(IsAnagram1(s2,t2))  cout<<"IsAnagram"<<endl;else cout<<"IsNotAnagram"<<endl;return 0;}

运行结果:



1.5:Write a method to replace all spaces in a string with ‘%20’.

即:写一个函数来把一个字符串中的所有空格代替成为'%20'。

算法:

1). 首先遍历一遍字符串统计空格的总数;
2). 然后从后向前再次对字符串进行解析:
·如果遇到了空格,那么将它替换为"%20";

·否则,把这个字符移动到新的空间中去。


代码:

#include<iostream>#include<string.h>using namespace std;void ReplaceFun(char *str){int NumOfSpace = 0 ,newLength,i=0;int len=strlen(str);/*统计空格的总个数*/for(i=0;i<len;i++){if(str[i]==' ')  NumOfSpace++;}newLength=len+2*NumOfSpace;    //得到将空格替换为'%20'后的字符串新长度str[newLength--]='\0';for(i=len-1;i>=0;i--){if(str[i]!=' ')  str[newLength--]=str[i];    //如果字符不是空格那么赋值即可else                                         //否则将空格替换为'%20' {str[newLength--]='0';str[newLength--]='2';str[newLength--]='%';}}}int main(){/*测试用例*/char s1[100]="I am the best one!";char s2[100]="   he he he   !";ReplaceFun(s1);ReplaceFun(s2);cout<<s1<<endl;cout<<s2<<endl;return 0;}
运行结果:




1.6:Given an image represented by an NxN matrix, where each pixel in the image is 4 bytes, write a method to rotate the image by 90 degrees. Can you do this in place?

即:给你一张由N*N表示的图片,图像中的每一个像素为4个字节,写一个算法来把这张图片旋转90度。你能原地完成吗?(即不使用额外的空间)

算法:我们假设按照逆时针对对矩阵进行旋转,假设逆时针旋转90度。例如

1  2  3           3  6  9

4  5  6  ==> 2  5  8

7  8  9           1  4  7

第一步:交换主对角线两侧的对称元素。

第二步:交换第i行和第n-1-i行,即得到结果。(只需要循环遍历半个列长度的矩阵)

代码:

#include<iostream>#include<stdlib.h>#include<math.h>using namespace std;void Swap(int &a, int &b)    //原地交换两个整数{a^=b;b^=a;a^=b;}void rotate(int *matrix[],int n){for(int i=0;i<n;i++)    //第一步:交换主对角线两侧的对称元素。for(int j=i+1;j<n;j++){Swap( *((int*)matrix+n*i+j),*((int*)matrix+n*j+i) );    //相当于:Swap(matrix[i][j],matrix[j][i])}for(int i=0;i<n/2;i++)    //交换第i行和第n-1-i行,即得到结果。(只需要循环遍历半个列长度的矩阵)for(int j=0;j<n;j++){Swap( *((int*)matrix+n*i+j),*((int*)matrix+n*(n-1-i)+j) );  //相当于:Swap(matrix[i][j],matrix[n-1-i][j])}}void display(int **matrix,int n)    //输出矩阵{for(int i=0;i<n;i++){for(int j=0;j<n;j++)cout<<*((int*)matrix+n*i+j)<<" ";    //matrix[i][j]cout<<endl;}cout<<endl;}int main(){int dimension;int a[4][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};dimension=(int)sqrt(sizeof(a)/4);cout<<"dimension:"<<dimension<<endl;cout<<"before rotate:"<<endl;display((int**)a,dimension);rotate((int**)a,dimension);cout<<"after rotate:"<<endl;display((int**)a,dimension);int b[3][3]={{1,2,3},{4,5,6},{7,8,9}};dimension=(int)sqrt(sizeof(b)/4);cout<<"dimension:"<<dimension<<endl;cout<<"before rotate:"<<endl;display((int**)b,dimension);rotate((int**)b,dimension);cout<<"after rotate:"<<endl;display((int**)b,dimension);return 0;}
运行结果:



关于函数传递不同纬度的二维数组的方法和原理:http://blog.csdn.net/liyongbao1988/article/details/7463481


1.7:Write an algorithm such that if an element in an MxN matrix is 0, its entire row and column is set to 0.

即:实现一个算法,如果一个M*N的矩阵中的某个元素为0,那么把这个元素所在的行和列的元素全部置0。

算法:

1)一个这个题目好像很简单,只需要遍历矩阵中的每个元素,遇到一个0,那么就将它的行和列全都置0,但是如果这么下去,无法标记矩阵中的0是原来的0还是变化之后的0,最后整个矩阵全都会被变为0。

2)还有一种方法就是另外设置一个矩阵来标记0的位置。然后再第二次遍历矩阵来设置0.这样将会花费O(M*N)的空间。

3)实际上我们只需要O(M+N)的空间来进行,设置一个行数组row[m],列数组column[n]来记录原矩阵中某0元素所在行和列的情况,然后遍历row和column数组,将原矩阵相应的行和列置0。

代码:

#include<iostream>#include<memory.h>#include<string>using namespace std;void setZeros(int **matrix,int m,int n){int row[m],column[n];memset(row,0,sizeof(row));memset(column,0,sizeof(column));//store the row and column index with value 0for(int i=0;i<m;i++){for(int j=0;j<n;j++){if( *((int*)matrix+n*i+j) == 0 )// matrix[i][j]==0{row[i]=1;column[j]=1;}}}//set arr[i][j] to 0 if either row i or column j has a 0for(int i=0;i<m;i++){for(int j=0;j<n;j++){if( row[i]==1 || column[j]==1  ){*((int*)matrix+n*i+j)=0;//matrix[i][j]=0;}}}}void display(int **matrix , int m ,int n){for(int i=0;i<m;i++){for(int j=0;j<n;j++)cout<<*((int*)matrix+n*i+j)<<" ";cout<<endl;}}int main(){int a[3][4]={{0,1,1,0},{1,1,1,1},{0,1,0,1}};setZeros((int**)a,3,4);cout<<"a:"<<endl;display((int**)a,3,4);int b[5][4]={{1,0,1,0},{0,1,1,0},{0,0,1,1},{1,0,1,1},{1,1,1,1}};setZeros((int**)b,5,4);cout<<"b:"<<endl;display((int**)b,5,4);return 0;}

运行结果:



1.8:Assume you have a method isSubstring which checks if one word is a substring of another. Given two strings, s1 and s2, write code to check if s2 is a rotation of s1 using only one call to isSubstring (i.e., “waterbottle” is a rotation of “erbottlewat”).

即:假设有一个函数isSubstring,它可以判断一个单词是否是另一个单词的子串。现在有两个string类型的字符串s1,s2,写代码来判断只调用一次isSubstring,s2是不是s1的自转。(例如,"waterbottle"是"erbottlewat"的自转)

算法:只需要做如下的检验:

1).判断s1和s2的长度是否相等。如果不等,那么返回false。

2).然后将s1自身串联起来得到s1s1,然后观察s2是不是s1s1的子串即可。

input: s1 = apple, s2 = pleap ==> apple is a substring of pleappleap
input: s1 = apple, s2 = ppale ==> apple is not a substring of ppaleppale

代码:

#include<iostream>#include<string>using namespace std;bool isSubstring(string s1,string s2)    //判断s1是否包含s2子串的函数 {if(s1.find(s2)!=string::npos) return true;    //关于npos的定义参考:http://www.cnblogs.com/web100/archive/2012/12/02/cpp-string-find-npos.html else return false;}bool isRotation(string s1,string s2){if( s1.length()!=s2.length() ) return false;string s1s1=s1+s1;return isSubstring(s1s1,s2);}int main(){string s1="apple",s2="pleap";string s3="waterbottle",s4="bottlewater";string s5="apple",s6="ppale";if(isRotation(s1,s2)) cout<<"isRotation"<<endl;else cout<<"notRotation"<<endl;if(isRotation(s3,s4)) cout<<"isRotation"<<endl;else cout<<"notRotation"<<endl;if(isRotation(s5,s6)) cout<<"isRotation"<<endl;else cout<<"notRotation"<<endl;return 0;}
运行结果:





        转载请注明文章出处:http://blog.csdn.net/lavorange/article/details/9771993


原创粉丝点击