1. 程式人生 > >演算法機考模擬題

演算法機考模擬題

一、

1、題目描述

Description

定義超級和函式F如下:

F(0, n) = n,對於所有的正整數n.. F(k, n) = F(k – 1, 1) + F(k – 1, 2) + … + F(k – 1, n),對於所有的正整數k和n. 請實現下面Solution類中計算F(k, n)的函式(1 <= k, n <= 14). class Solution { public:        int F(int k, int n) {        } }; 例1:F(1, 3) = 6 例2:F(2, 3) = 10 例3:F(10, 10) = 167960 注意:你只需要提交Solution類的程式碼,你在本地可以編寫main函式測試程式,但不需要提交main函式的程式碼. 注意不要修改類和函式的名稱.

2、考點及思路

考查分治思想,將一個大問題劃分為一個小問題,並通過遞迴的方式完成小問題。

3、程式碼實現

class Solution {
public:
    int F(int k, int n) {
        if(k==0) return n;
        else{
            int sum=0;
            for(int i=1;i<=n;i++){
                sum+=F(k-1,i);
            }
            return sum;
        }
    }
};    

二、

1、題目描述

Description N個會議要同時舉行,參會人數分別為A[0], A[1], ..., A[N-1]. 現有M個會議室,會議室可容納人數分別為B[0], B[1], ..., B[M-1]. 當A[i]<=B[j]時,可以把會議i安排在會議室j,每間會議室最多安排一個會議,每個會議最多隻能安排一個會議室. 求最多安排多少個會議. 1 <= N, M <= 100000, 每個會議的參會人數和每間會議室的容納人數均在1和1000之間. 請為下面的Solution類實現解決上述問題的函式assignConferenceRoom. 函式引數A和B的意義如上,返回值為最多可安排的會議數. class Solution { public:     int assignConferenceRoom(vector<int>& A, vector<int>& B) {     } }; 例1:A={2, 3}, B={1, 2},答案為1. 例2:A={3, 4, 5},B={10, 3, 2},答案為2. 注意:你只需要提交Solution類的程式碼,你在本地可以編寫main函式測試程式,但不需要提交main函式的程式碼. 注意不要修改類和函式的名稱.

2、考點及思路

考查貪心演算法,將兩個陣列排序,並用最大會議室去滿足最大需求,無法滿足則看次之的需求。

3、程式碼實現

class Solution {
public:
    int assignConferenceRoom(vector<int>& A, vector<int>& B) {
        sort(A.begin(),A.end());
        sort(B.begin(),B.end());
        int a=A.size()-1;
        int b=B.size()-1;
        int count=0;
        while(a>=0&&b>=0){
            if(B[b]<A[a]){
                a--;
            }
            else{
                b--;
                a--;
                count++;
            }
        }
        return count;
    }
};                                 

三、

1、題目描述

Description 兩個二叉樹結構相同,且對應結點的值相同,我們稱這兩個二叉樹等價. 例如:以下兩個二叉樹等價         1           1        /  \         /  \       2   3       2   3 而以下兩個則不等價         1           1        /  \         /  \       2   3       3   2 以下兩個也不等價         1           1        /  \         /  \       2   3       2   2 給出兩個二叉樹p和q,判斷它們是否等價. p和q的結點數不多於100000,每個結點的數值在1和1000000000之間. 請為下面的Solution類實現解決上述問題的isEqual函式,函式的兩個引數p和q分別代表兩個二叉樹的根節點,如果以p和q為根的二叉樹等價則函式返回true,否則返回false. /**   Definition for a binary tree node.   struct TreeNode {       int val;       TreeNode *left;       TreeNode *right;       TreeNode(int x) : val(x), left(NULL), right(NULL) {}   };  */ class Solution { public:        bool isEqual(TreeNode* p, TreeNode* q) {     } }; 注意:你只需要提交Solution類的程式碼,你在本地可以編寫main函式測試程式,但不需要提交main函式的程式碼,也不需要提交TreeNode的定義. 注意不要修改類和函式的名稱.

2、考點及思路

考查DFS,通過DFS搜尋兩棵樹,對比檢視是否相同,我使用的是遞迴實現版本。

3、程式碼實現

class Solution {
public:
    bool isEqual(TreeNode* p, TreeNode* q) {
        if(p==NULL&&q==NULL)
            return true;
        if((p==NULL&&q!=NULL)||(q==NULL&&p!=NULL))
            return false;
        if(p->val!=q->val)
            return false;
        else
            return (isEqual(p->left,q->left)&&isEqual(p->right,q->right));
    }
};                                 

四、

1、題目描述

Description 對於一個01矩陣A,求其中有多少片連成一片的1. 每個1可以和上下左右的1相連. 請為下面的Solution類實現解決這一問題的函式countConnectedOnes,函式引數A為給出的01矩陣,A的行數和列數均不大於1000. 函式的返回值是問題的答案. class Solution { public:     int countConnectedOnes(vector<vector<char>>& A) {     } }; 例1: A= 100 010 001 答案為3. 例2: A= 1101 0101 1110 答案為2. 注意:你只需要提交Solution類的程式碼,你在本地可以編寫main函式測試程式,但不需要提交main函式的程式碼. 注意不要修改類和函式的名稱.

2、考點及思路

考查BFS,通過BFS尋找一個點所連線的所有點,我使用queue記錄同一層的節點。

3、程式碼實現

class Solution {
public:
    int countConnectedOnes(vector<vector<char>>& A) {
        int m = A.size();
        if (m == 0) return 0;
        int n = A[0].size();
        if (n == 0) return 0;
        vector<vector<bool>> B(m, vector<bool>(n, false));
        int count = 0;
        for (int i = 0; i<m; i++) {
            for (int j = 0; j<n; j++) {
                if (A[i][j] == '1'&&B[i][j] == false) {
                    count++;
                    BFS(A, B, i, j);
                }
            }
        }
        return count;
    }

    void BFS(vector<vector<char>>& A, vector<vector<bool>>& B, int i, int j) {
        queue<pair<int, int>> que;
        que.push(make_pair(i, j));
        while (!que.empty()) {
            pair<int, int> p = que.front();
            que.pop();
            if (p.first -1  >= 0  && A[p.first -1][p.second] == '1'&&B[p.first - 1][p.second] == false) {
                que.push(make_pair(p.first - 1, p.second));
                B[p.first - 1][p.second] = true;
            }
            if (p.first + 1 <A.size() && A[p.first + 1][p.second] == '1'&&B[p.first + 1][p.second] == false) {
                que.push(make_pair(p.first + 1, p.second));
                B[p.first + 1][p.second] = true;
            }
            if (p.second - 1 >= 0 && A[p.first][p.second-1] == '1'&&B[p.first][p.second-1] == false) {
                que.push(make_pair(p.first, p.second-1));
                B[p.first][p.second-1] = true;
            }
            if (p.second + 1 < A[0].size() && A[p.first][p.second + 1] == '1'&&B[p.first][p.second + 1] == false) {
                que.push(make_pair(p.first, p.second + 1));
                B[p.first][p.second + 1] = true;
            }
        }
    }
};                                 

五、

1、題目描述

Description 在圖論中,如果一個有向圖從任意頂點出發無法經過若干條邊回到該點,則這個圖是一個有向無環圖(Directed Acyclic Graph,DAG). 對於一個n個節點的有向圖(節點編號從0到n-1),請判斷其是否為有向無環圖. 圖的節點數和邊數均不多於100000. 請為下面的Solution類實現解決上述問題的isDAG函式,函式引數中n為圖的節點數,edges是邊集,edges[i]表示第i條邊從edges[i].first指向edge[i].second. 如果是有向無環圖返回true,否則返回false. class Solution { public:        bool isDAG(int n, vector<pair<int, int>>& edges) {     } }; 例1: n = 3,edges = {(0, 1), (0, 2)},函式應返回true. 例2: n = 2,edges = {(0, 1), (1, 0)},函式應返回false. 注意:你只需要提交Solution類的程式碼,你在本地可以編寫main函式測試程式,但不需要提交main函式的程式碼. 注意不要修改類和函式的名稱.

2、考點及思路

考查圖論知識,我在檢查是否有回邊的過程中使用了dfs進行檢索。

3、程式碼實現

class Solution {
public:
    bool isDAG(int n, vector<pair<int, int>>& edges) {
        vector<vector<int>> graph(n);
        for (int i = 0; i < edges.size(); i++) 
            graph[edges[i].first].push_back(edges[i].second);
        vector<bool> visited(n, false);
        vector<bool> onpath(n,false);
        for (int i = 0; i < n; i++)
            if (has_circle(graph,i,visited,onpath))
                return false;
        return true;
    }

    bool has_circle(vector<vector<int>>& graph, int node, vector<bool>& visited, vector<bool>& onpath) {
        if (visited[node]) return false;
        onpath[node] = visited[node] = true;
        for (int i = 0; i < graph[node].size(); i++) {
            if (onpath[graph[node][i]] || has_circle(graph, graph[node][i], visited, onpath))
                return true;
        }
        onpath[node] = false;
        return false;
    }
};                                 

六、

1、題目描述

Description 從數列A[0], A[1], A[2], ..., A[N-1]中選若干個數,要求相鄰的數不能都選,也就是說如果選了A[i], 就不能選A[i-1]和A[i+1]. 求能選出的最大和. 1 <= N <= 100000, 1 <= A[i] <= 1000 請為下面的Solution類實現解決上述問題的函式maxSum,函式引數A是給出的數列,返回值為所求的最大和. class Solution { public:     int maxSum(vector<int>& A) {     } }; 例1:A = {2, 5, 2},答案為5. 例2:A = {2, 5, 4},答案為6. 注意:你只需要提交Solution類的程式碼,你在本地可以編寫main函式測試程式,但不需要提交main函式的程式碼. 注意不要修改類和函式的名稱.

2、考點及思路

考查動態規劃,定義函式並寫出狀態轉移方程即可。

3、程式碼實現

class Solution {
public:
    int maxSum(vector<int>& A) {
        if (A.size() == 0) return 0;
        vector<int> f(A.size());
        f[0] = A[0];
        f[1] = A[0] > A[1] ? A[0] : A[1];
        for (int i = 2; i < A.size(); i++) {
            f[i] = f[i - 1] > (f[i - 2] + A[i]) ? f[i - 1] : (f[i - 2] + A[i]);
        }
        return f[A.size() - 1];
    }
};                                 

七、

1、題目描述

Description 對於兩個只含有小寫英文字母(’a’-‘z’)的單詞word1和word2,你可以對word1進行以下3種操作: 1) 插入一個字母; 2) 刪除一個字母; 3) 替換一個字母. 請計算將word1變換成word2的最少運算元. word1和word2的長度均不大於1000. 請為下面的Solution類實現解決上述問題的函式minDistance,函式的引數word1和word2為給出的兩個單詞,返回值為所求最少運算元. class Solution { public:     int minDistance(string word1, string word2) {        } }; 例1:word1 = “sunny”, word2 = “snowy”,返回值為3. 例2:word1 = “abc”, word2 = “ac”,返回值為1. 注意:你只需要提交Solution類的程式碼,你在本地可以編寫main函式測試程式,但不需要提交main函式的程式碼. 注意不要修改類和函式的名稱.

2、考點及思路

考查動態規劃。需要注意dp[i][j]表示長度為i的word1與長度為j的word2的單詞距離,dp的兩個維度的長度分別為m+1,n+1,同時dp[i][j]對應的最後一個字元是字串word1[i-1]和word2[j-1]。

3、程式碼實現

class Solution {
public:
    int minDistance(string word1, string word2) {
        int x= word1.length();
        int y= word2.length();
        vector<vector<int>> dp(x+1,vector<int>(y+1,0));
        for(int i=0;i<=x;i++){
            dp[i][0]=i;
        }
        for(int j=0;j<=y;j++){
            dp[0][j]=j;
        }
        for(int i=1;i<=x;i++){
            for(int j=1;j<=y;j++){
                if(word1[i-1]==word2[j-1])
                    dp[i][j]=dp[i-1][j-1];
                else{
                    dp[i][j]=min(dp[i-1][j-1],min(dp[i][j-1],dp[i-1][j]))+1;
                }
            }
        }
        return dp[x][y];
    }
};