Crack The Code Interview第一章Arrays & Strings讀書筆記

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

如果只是要判斷有沒有重複的字符,使用一個bool的數組是一個很簡單的方案:

bool isUniqueCharStr(string str){
  bool carray[256];
  int size = str.size();
  for(int i = 0; i < size; ++i){
    if(carray[ str[i] ]){
      return false;
    } else {
      carray[ str[i] ] = true;
    }
  }
  return true;
}

該算法的時間複雜度和空間複雜度都是O(n).考慮到題目中要求不使用額外的內存的話,可以以時間換取空間的方式,循環嵌套。

bool isUniqueCharStr_slow(string str){
	int size = str.size();

	for(int i = 0; i < size - 1; ++i){
		for(int j = i+1; j < size; ++j){
			if(str[j] == str[i]){
				return false;
			}
		}
	}
	return true;
}

這種算法是暴力式遍歷,時間複雜度達到O(n^2),但是空間複雜度較低O(1)。

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

這個比較簡單,主要考察字符串以'\0'爲結束標誌,簡單寫一下代碼:

void reverse_c_str(char* str){
  int len = strlen(str);
  int i, j;
  char tmp;
  for(i = 0, j = len-1; i < j; i++, j--){
    tmp = str[i];
    str[i] = str[j];
    str[j] = tmp;
  }
}

值得注意的是,這裏strlen的時間複雜度爲O(n),當然,這是不可避免的,整個算法時間O(n),空間O(1)。

3.Design an algorithm and write code to remove the duplicate characters in a stringwithout using any additional buffer. NOTE: One or two additional variables are fine.An extra copy of the array is not

題目難點在於要使用O(1)的空間複雜度。可以把重複的字符標記成一個特殊字符,在第二遍遍歷時刪除。

void remove_dup_char2(char *str){
	if( str == NULL) return;

	int size = strlen(str);
	if(size <= 2) return;

	char flg = *str;

	for(int i = 0; i < size-1; ++i){
		for(int j = i+1; j < size; ++j){
			if( str[j] == str[i] ){
				str[j] = flg;
			}
		}
	}

	int idx = 1;
	for(int i = 1; i < size; ++i){
		if(str[i] == flg){
			continue;
		} else {
			str[idx] = str[i];
			idx++;
		}
	}
	str[idx] = '\0';
}

上面的算法時間複雜度O(n^2),空間複雜度O(1)。

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

題目要求判斷兩個string是不是“變位詞”,所謂“變位詞”就是指,兩個單詞中所包含的字母相同只是順序不同。比較直觀的方法是對每個string中字符出現的個數進行統計,然後再進行比較。

bool anagram(string str1, string str2)
{
    int letters[256];
    int num_chars = 0;
    int num_completed = 0;

    for(int i = 0; i < 256; i++)
    {
        letters[i] = 0;
    }

    int size1 = str1.size();
    int size2 = str2.size();

    for(int i = 0; i < size1; i++)
    {
        if(letters[ str1[i] ] == 0)
            num_chars++;
        letters[ str1[i] ]++;
    }

    for(int i = 0; i < size1; i++)
    {
        if(letters[ str2[i] ] == 0)
            return false;
        letters[ str2[i] ] --;
        if(letters[ str2[i] ] == 0)
        {
            num_completed++;
            if(num_chars == num_completed)
            {
                return i == size1-1;
            }
        }
    }
}


算法時間複雜度O(n),空間複雜度O(n)。需要注意的是:連個string有可能是多長的字符串? 這樣可以根據字符串的規模選取count_char的類型。


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

這個題目的主要難點在於,轉換之後的字符串要比轉換之前長很多,並且,書上給出的答案相當詭異,下面是書本上給出的解答:

public static void ReplaceFun(char[] str, int length) {
  int spaceCount = 0, newLength, i = 0;	
  for (i = 0; i < length; i++) {
    if (str[i] == ‘ ‘) {		
      spaceCount++;	
    }	
  }
  newLength = length + spaceCount * 2;
  str[newLength] = ‘\0’;
  for (i = length - 1; i >= 0; i--) {
    if (str[i] == ‘ ‘) {
      str[newLength - 1] = ‘0’;
      str[newLength - 2] = ‘2’;
      str[newLength - 3] = ‘%’;
      newLength = newLength - 3;
    } else {
      str[newLength - 1] = str[i];
      newLength = newLength - 1;		
    }	
  }
}

方法本身很容易理解,但是,如果str後面的內存是已使用的,那麼會造成內存錯誤。



 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?

簡單理解爲使用O(1)的輔助空間把一個NxN的int類型的矩陣旋轉90度。對於這個題,只要找到旋轉後的矩陣和旋轉前矩陣的座標關係就okay了。這個並不難,只要求出矩陣的轉秩矩陣,然後在對每行(順時針旋轉)或者每列(逆時針旋轉)逆序就行了。

void rotate_matrix(int a[10][10]){
  if(a == NULL) return;
  int tmp = 0;
  for(int i = 0; i < 10; ++i){
    for(int j = 0; j < 10; ++j){
      tmp = a[i][j];
      a[i][j] = a[j][i];
      a[j][i] = tmp;
    }
  }

  int j,k;
  //假設順時針
  for(int i = 0; i < 10; i++){
    for(j = 0, k = 9; j < k; ++j, --k){
      tmp = a[i][j];
      a[i][j] = a[i][k];
      a[i][k] = tmp;
    }
  }
}

時間複雜度O(n^2),空間複雜度O(1)。

原書中給出的解答是這樣的:

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]; // save top

	     // left -> top

	    matrix[first][i] = matrix[last-offset][first]; 			
		 // bottom -> left
	    matrix[last-offset][first] = matrix[last][last - offset];
	    // right -> bottom
	    matrix[last][last - offset] = matrix[i][last];
	    // top -> right
	    matrix[i][last] = top; // right <- saved top

	} 

  } 
}

 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”).

《編程之美》上的老題目了:

char a[] = "AABCD";
char b[] = "CDAA";
int i, j, res;
char tmp;
int len = strlen(a);

for(i = 0; i < len; i++){
 tmp = a[0];
 for(j = 0; j < len-1; j++){
     a[j] = a[j+1];
 }
 a[len-1] = tmp;

 if(strstr(a,b)){
     printf("OK");
     return 0;
 }
}
printf("NOT OK");

這一章的例子都不難,但是要給出來一個比較完美的解答還是需要很多思考。要寫出“正確”的代碼就更需要細心。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章