程式設計師面試金典Chapter1

catamo10發表於2019-05-13
第一題 翻轉字串

把一個給定的字串反轉
笨方法,遍歷整個給定的string,將陣列string[n]中的第i個元素與第[n-1-i]個元素對調,下面為程式碼示例:


    class Reverse {
    public:
        string reverseString(string iniString) {
            // write code here
            char c;
            int len = iniString.length();
            for(int i=0; i < len / 2; i ++)
            {
             c = iniString[i];
                iniString[i] = iniString[len - i - 1];
                iniString[len - i - 1] = c;
            }
            return iniString;
        }
    };
第二題 判定字串中字元是否相同或不同


不細說、程式碼示例在下面:


class Different {
public:
    bool checkDifferent(string iniString) {
        // write code here
        for(int i=0;iniString[i]!=` `;i++)
            {
            for(int j=i+1;iniString[j]!=` `;j++){
                if(iniString[i] == iniString[j])
                    return 0;
            }
        }
            return 1;
    }
};
第三題 確定兩串亂序同構

(我覺得和第八題是一樣的,這裡是第八題的描述:
請將這個演算法編寫成一個函式,給定兩個字串s1和s2,請編寫程式碼檢查s2是否為s1旋轉而成。唯一不一樣的地方可能就是第八題要求用並且只用一次issubstring這個函式吧。這裡省略第八題。
)

給出的程式碼結構為:

class Same {
public:
    bool checkSam(string stringA, string stringB) {
        // write code here
};

我的第一個想法很簡單,遍歷整個stringA和stringB,當在B中能找到該元素就在B陣列中刪除這個元素,直到最後判斷B是否為空。但是….總之我這麼想著寫有誤,會漏判應該返回 “false”的情況,下面為錯誤的程式碼示例:

class Same {
public:
    bool checkSam(string stringA, string stringB) {
        // write code here
        if(stringA.length()!=stringB.length())
            return false;
       for(int i=0;stringA[i]!=` `;i++){
           for (int j=0;stringB[j]!=` `;j++){
               if(stringA[i] == stringB[j]){
                   stringB.erase(j,1);
               }
           }
       }
        stringB.erase(` `);  //delete the last element in the string
        if(stringB.empty())
            return true;
        return false;
    }
};

既然漏判了一個原本應該為”false”的情況那麼我就加判一個,同樣遍歷A,當不能在B中找到A的該元素時我就立即返回”false”.一下為通過的程式碼示例:

class Same {
public:
    bool checkSam(string stringA, string stringB) {
        // write code here
        if(stringA.length()!=stringB.length())
            return false;
       for(int i=0;stringA[i]!=` `;i++){
           for (int j=0;stringB[j]!=` `;j++){
               if(stringA[i] == stringB[j]){
                   stringB.erase(j,1);
                   break;
               }
               else if((stringA[i] != stringB[j]) && (j == stringB.length()-1))
                   return false;
           }
       }
        stringB.erase(` `);
        if(stringB.empty())
            return true;
        return false;
    }
};

在看別人的討論中看到大神們是這麼想的,還是一樣先從最簡單的長度開始比較,然後定義一個存放了256個”0″的新陣列,當在遍歷的時候將A中的元素和B中的元素逐一進行記錄,遇到A中的第n個元素該新定義的的陣列的第[A[n]]個”0″自增1,而同樣,遇到B的元素時自減1.也就是說若A和B是完全相同的組合陣列那麼意味著這個新定義的陣列始終應該保持“0”的平衡。下面是該方法的程式碼示例:


class Same {
public:
    bool checkSam(string stringA, string stringB) {
        // write code here
        char count[256]={0};
        if(stringA.size()!=stringB.size()) return false;
          
        for(int i=0;i<stringA.size();i++)
        {
            count[stringA[i]]++;
                count[stringB[i]]--;
        }
        for(int i=0;i<256;i++)
            if(count[i]!=0)
                return false;
        return true;
    }
};

我自己的本方法雖然最後執行結果正確但是執行時間相當長,我的正確程式碼執行時間為70ms而大神的程式碼只需要1ms。

第四題 將字串中的空格全部替換為”%20″

給出的程式碼格式為:

class Replacement {
public:
    string replaceSpace(string iniString, int length) {
        // write code here
        
    }
};

簡單的想,首要任務應該就是找找這個字串裡面哪裡有空格,哪裡有空格就在哪裡新增那個”%20″唄。簡單的程式碼示例為:


class Replacement {
public:
    string replaceSpace(string iniString, int length) {
        // write code here
        string str;
        for(int i=0;i<length;i++)
        {
            if(iniString[i]==` `)
            {
                str+="%20";
            }else
            {
                str+=iniString[i];
            }
        }
        return str;
    }
};
第五題 壓縮字串

利用字元重複出現的次數,編寫一個方法,實現基本的字串壓縮功能。比如,字串“aabcccccaaa”經壓縮會變成“a2b1c5a3”。若壓縮後的字串沒有變短,則返回原先的字串。

好吧,一開始沒怎麼明白看了好幾遍輸出才知道臥槽根本不存在壓縮後面不帶數字的情況啊。。。。思路很簡單總之就是j的迴圈在i裡面,期間犯了個很大錯誤導致最後一個元素會列印不出來,原因在於內迴圈的j也設了不能到字串最後的條件,來看一下這個判斷:

for(int i=0;i<iniString.length();){
            for(j=i;j<iniString.length();){
                if(iniString[i] == iniString[j]){
                    count++;
                    j++;
                }
                else{
                       str+=iniString[i];
                       str+=to_string(count);
                    count=0;
                    break;
                }
            }
            i=j;
        }

我估計之所以不能get到最後的元素可能是因為這樣寫的後果。。。j到不了字串最後的` `,以至於最後比較的時候沒辦法”j++”。所以最終通過程式碼為:

class Zipper {
public:
    string zipString(string iniString) {
        // write code here
        string str;
        int j=0;
        int count=0;
        for(int i=0;i<iniString.length();){
            for(j=i;;){
                if(iniString[i] == iniString[j]){
                    count++;
                    j++;
                }
                else{
                       str+=iniString[i];
                       str+=to_string(count);
                    count=0;
                    break;
                }
            }
            i=j;
        }
        
        if(str.length() >= iniString.length())
            return iniString;
        return str;
    }
};
第六題 畫素翻轉

需要返回一個旋轉後的NxN矩陣
函式樣例給出如下:

class Transform {
public:
    vector<vector<int> > transformImage(vector<vector<int> > mat, int n) {
        // write code here
    }
};

既然不能定義一個新的temp陣列可能從替換的角度來思考這個問題更簡便一些,首先從矩陣最外圍的一圈來看:

for(int i=0;i<n/2;i++){
 //... ...
}

假如說該原始矩陣有單數層那麼理應只需要進行(n-1)/2次分層就可以了,比如三層,去掉最外圍就只剩下中間的一個元素,應該不動。若是偶數層正好除盡,進行n/2次的處理。那麼對於每一層來說有四條邊,就在每一層中間做需要做四次的操作:

for(int i=0;i<n/2;i++){
    for(int j=i;j<n-1-i;j++){
        mat[i][j]=mat[n-j-1][i];
  }
}

第一次處理第一行的元素,變換後的矩陣第一行由第一列來取代,將內迴圈的j看作是列的話,那麼挨個的元素替換就相當於是將該列最後一個元素n-0-1替換到了0的位置,而後以此類推。
第二次處理應該處理剛剛替換的位置的元素也就是第一列的元素,第一列的元素是被最後一行的元素鎖替代,那麼程式碼示例為:

mat[n-j-1][i]=mat[n-i-1][n-j-1];

也就是說第一列最後一個元素n-0-1被替換成了n-0-1也就是最後一行的最後一個元素了,以此類推。
繼續第三次是把剛剛替換了第一列的元素,也就是原矩陣最後一行的元素進行處理,換成原矩陣的最後一列元素。最後將原矩陣第一行的元素放入原矩陣最後一列的元素,第一層就替換完畢了。
最後完整程式碼示例為:

class Transform {
public:
    vector<vector<int> > transformImage(vector<vector<int> > mat, int n) {
    // write code here
    int temp;
    for(int i=0;i<n/2;i++){
      for(int j=i;j<n-1-i;j++){
          temp = mat[i][j];
          mat[i][j]=mat[n-j-1][i];
          mat[n-j-1][i]=mat[n-i-1][n-j-1];
          mat[n-i-1][n-j-1]=mat[j][n-i-1];
          mat[j][n-i-1]=temp;
      }
  }
    return mat;
    }
};
第七題 清除矩陣中整行整列

還是遍歷整個矩陣,也就是一個二維陣列,找到0就返回flag該行該列都應該為0。那麼返回的這個flag通過定義兩個新的一維陣列來實現簡單的記錄,通過程式碼示例為:

class Clearer {
public:
    vector<vector<int> > clearZero(vector<vector<int> > mat, int n) {
        // write code here
        //vector<int> row(n,1),column(n,1);
        int row[n],column[n];
        for(int i=0;i<n;i++){
            row[i]=0;
            column[i]=0;
        }
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                if(mat[i][j] == 0){
                    row[i]=1;
                    column[j]=1;
                }
            }
        }
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                if(row[i]==1 || column[j]==1){
                    mat[i][j]=0;
                }
            }
        }
        return mat;
    }
};

我的部落格原文、戳我

相關文章