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; //如果所对应的字符存在,即有相同字符,那么返回false char_set[val]=true; //如果相应字符第一次出现,那么将其标记为true } return true; //遍历所有字符都没有重复,则返回true } //时间复杂度为O(n),我们还可以通过位运算来减少空间的使用量。 用每一位表征相应位置字符的出现。 //对于ASCII字符,我们需要256位,即一个长度为8的int 数组a即可。这里的关键是要把字符对应的数字, //映射到正确的位上去。比如字符'b'对应的代码是98,那么我们应该将数组中的哪一位置为1呢? //用98除以32,得到对应数组a的下标: 3。98对32取模得到相应的位:2 bool 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更简洁 void reverse2(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 0 for(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 0 for(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