Cracking the Coding Interview
1.1实现一个算法判断一个字符串是否存在重复字符。如果不能利用另外的数据结构又该如何实现?
My solution:
/** *利用类似一个hash table的计数 *然后检查这个hash table计数,时间复杂度(n) */ int unique_string1( char *array, int length) { int CARRAY[26] = {0}; int i; if (length > 26) return 0; for (i = 0;i < length;i++) CARRAY[array[i]- 'a' ]++; for (i = 0;i < 26;i++) if (CARRAY[i] > 1) return 0; return 1; } |
/** *直接双重循环检查,时间复杂度O(n^2) */ int unique_string2( char *array, int length) { int i,j; if (length > 26) return 0; for (i = 0;i < length;i++) for (j = i+1;j < length;j++) if (array[i] == array[j]) return 0; return 1; } |
The Solution that the book advice:
1.思路类似于我第一种实现的方法,但是其中是一个存放boolean值的hashtable,遇到一个字符将其位置设置为true,检查每次遇到的字符hashtable的位置boolean值是否被设置,时间复杂度O(n),但是略优于我的实现。
2.不能利用额外的数据结构,但是仍然不增加时间复杂度的另外一种方法,利用bit vector,即每一位记录当做一个boolean值对待,这样如果仅仅26个字符,则一个整形int即可,其占32位。
3.另外还有一些其他的思路,比如排序。时间复杂度为O(nlgn)
1.2实现一个逆序C-String字符串的方法。
My Solution:
void swap( char &a, char &b) { char temp; temp = a; a = b; b = temp; return ; } void reverse_Cstring( char *array, int length) { if (length == 0) return ; int i; for (i = 0;i < length/2;i++) { swap(array[i],array[length-1-i]); } return ; } |
The Solution that the book advice:
其实思路是类似的,但是可能C-String不能得到length这个值,所以解决办法是检查直到遇到C-String的结尾字符。' '
1.3设计一个移除String中重复字符的算法并且不能够利用额外的buffer。
My Solution:
int remove_dupchar( char *array, int length) { int i,j,k; for (i = 0;i < length;i++) for (j = i+1;j < length;j++) if (array[i] == array[j]) { for (k = j+1;k < length;k++) array[k-1] = array[k]; length --; j --; } array[length] = ' ' ; return length; } |
The Solution that the book advice:
1. step1,for each character,check if it is a duplicate of already found characters. step2,skip duplicate characters and update the non duplicate characters.
code:
public static void removeDuplicates( char [] str) { if (str == null ) return ; int len = str.length(); if (len < 2 ) return ; int i,j; int tail = 1 ; for (i = 1 ;i < len;i++) { for (j = 0 ;j < i;j++) { if (str[i] == str[j]) break ; } if (j == tail) { str[tail++]=str[i]; } } str[tail]= 0 ; } |
2.利用常量长度的额外内存。
code:
public static void removeDuplicatesEff( char [] str) { if (str == null ) return ; int len = str.length(); if (len < 2 ) return ; boolean [] hashtablesign = new boolean [ 256 ]; int i; for (i = 0 ;i < len;i++) { hashtablesign[i]= false ; } hashtablesign[str[ 0 ]] = true ; int tail = 1 ; for (i = 1 ;i < len;i++) { if (!hashtablesign[str[i]]) { str[tail++] = str[i]; hashtablesign[str[i]] = true ; } str[tail]= 0 ; } |
1.4实现一个判断两个字符串是否回文的方法。(回文:两个字符串由相同的字符组成,顺序可以不同)
My Solution:
int is_anagram( char *a, char *b, int length) { int CARRAY[26]={0}; int i; for (i = 0;i < length;i ++) { CARRAY[a[i]- 'a' ]++; CARRAY[b[i]- 'a' ]--; } for (i = 0;i < 26;i++) { if (CARRAY[i] != 0) { return 0; } } return 1; } |
1.5实现一个方法,将一个字符串中的空格替换为"%20"
My Solution:
char * replace_space( char *array, int length) { int i; int s_count = 0; for (i = 0;i < length;i++) { if (array[i] == ' ' ) { s_count++; } } int j = 0; int new_length = (length-s_count)+3*s_count; char *new_array = new char [new_length]; for (i = 0;i < length;i++) { if (array[i] == ' ' ) { new_array[j++] = '%' ; new_array[j++] = '2' ; new_array[j++] = '0' ; } else { new_array[j++]=array[i]; } } return new_array; } |
1.6给出一个N*N的矩阵。每个像素点4bytes,实现一个方法将该矩阵旋转90度。可以不利用额外的存储空间实现吗?
My Solution:
不利用额外的存储空间有一句叫in place,快速排序也可以成为原地排序。
public static void rotate( int [][] matrix, int n) { for ( int layer = 0 ;layer < n/ 2 ;layer++) { int first = layer; int last = n- 1 -layer; for ( int i = first;i<last;i++) { int offset = i - first; int top = matrix[first][i]; matrix[first][i]=matrix[last-offset][first]; matrix[last-offset][first]=matrix[last][last-offset]; matrix[last][last-offset]=matrix[i][last]; matrix[i][last]=top; } } } |
1.7实现如下方法,如果一个M*N的矩阵中存在0元素,则将其行和列均设置为0。
My Solution:
这个题目容易犯错的地方在于如果是碰到一个0元素就将其行列置为0肯定最终得不到正确的结果,所以首先第一轮要保存0元素出现的位置,第二轮在设置行列为0.
1.8假设你现在已经实现了一个方法isSubString来检查一个字符串是否为另一个字符串的子串。现在给出两个字符串s1,s2,实现方法判断s2是否为s1的轮换通过只调用isSubString一次。
My Solution:
这个问题真的没有想到解决方案,但是看到答案之后发现题目真的很easy的。
The Solution that the book advice:
思路就是,将s2重新复制一遍然后连接起来,检查s1是否为s2的字串即可。
例如:s2=“cdab”,s1=“abcd”,首先s2扩展为 “cdabcdab”,检查s1是否为s2的子串即可。
public static void check(String str1 , String str2) { int len = str1.length(); if (len == str2.length() && len > 0 ) { String str1str1 = str1+str1; return isSubString(str1str1,str2); } return false ; } |