算法设计与分析期中练习题整理 2017

1000. 分组

Description

对于一个整数数列A[0], A[1], …, A[N-1]进行分组,要求每组1到2个数,并且同组之和不能大于w. 求最少可以分成多少组.

1 <= N <= 100000, 1 <= A[i] <= w <= 1000000000.

例1:当A = {2, 5, 4, 3}, w = 5, minPartition(A, w)返回3. 将2和3放一组,4和5各自单独作为一组,共3组.

例2:当A = {2, 5, 4, 3}, w = 7, minPartition(A, w)返回2. 将2和5放一组,3和4一组,共2组.

Solution

//我的答案

class Solution {
public:
    int minPartition(vector<int> tem, int w) {
        int count = 0;
        sort(tem.begin(), tem.end());
        int index = 0; 
        for(int i = tem.size() - 1; i >= index; i--) {
            if(tem[i] + tem[index] <= w) {
                index++;
            }
            count++;
        }
        return count;
    }
};  
// 老师答案

class Solution {
public:
    int minPartition(vector<int> A, int w) {
        int res, n, i, j;
        n = A.size();
        sort(A.begin(), A.end());
        res = 0;
        for (i=0,j=n-1; i<=j; j--) {
            if (A[i] + A[j] <= w) i++;
            res ++;
        }
        return res;
    }
};

1001. 最小差

Description

对于一个整数数列A[0], A[1], …, A[N-1],要求在其中找两个数,使得它们的差的绝对值最小.

2 <= N <= 100, -1000 <= A[i] <= 1000.

例1:当A = {2, 7, -2}, 返回4.

例2:当A = {-8, 10, 30, 10}, 返回0.

Solution

// 我的答案

class Solution {
public:
       int minDifference(vector<int> a) {
             sort(a.begin(), a.end());
             int min = 10000000;
             for(int i = 1; i < a.size(); i++) {
                 int tem = abs(a[i] - a[i-1]);
                 if(tem < min) min = tem;
             }
             return min;

       }
};   
//老师代码

class Solution {
public:
    int minDifference(vector<int> A) {
        int res, n, i;
        n = A.size();
        sort(A.begin(), A.end());
        res = 1000000000;
        for (i=0; i1; i++) res = min(res, A[i+1] - A[i]);
        return res;
    }
};

1002. 合并二叉树

Description

输入两个二叉树T1和T2,要求对T1和T2进行合并. 合并是指将二叉树同一位置节点上的数求和,作为合并后二叉树相应位置节点的数值. 如果某个位置上只有一个二叉树有节点,则合并后的二叉树对应位置上的节点上的数值就等于这个节点上的数值.

例如:

          T1                        T2

          1                         2                            
         /  \                       /  \                           
        3   2                       1   3                       
       /                            \    \                      
      5                              4   7  

合并后:


            3
           /  \
          4    5
         /  \    \
        5    4    7

T1和T2的结点数均不多于100000,每个结点的数值在1和1000之间.

Solution

//我的代码

/**
  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:
       TreeNode* merge(TreeNode* a, TreeNode* b) {
           if (!a) return b;
           if (!b) return a;
           TreeNode *t = new TreeNode(a->val + b->val);
           t->left = merge(a->left, b->left);
           t->right = merge(a->right, b->right);
           return t;
       }
};
//老师代码

class Solution {
public:
    TreeNode* merge(TreeNode* T1, TreeNode* T2) {
        if (!T1 && !T2) return NULL;
        if (!T1) return T2;
        if (!T2) return T1;
        TreeNode* T = new TreeNode(T1->val + T2->val);
        T->left = merge(T1->left, T2->left);
        T->right = merge(T1->right, T2->right);
        return T;
    }
};

1003. 最近的0

Description

输入一个N*M的01矩阵A,对矩阵的每个位置,求至少经过多少步可以到达一个0. 每一步可以往上下左右走一格.

例如:
A=
1 1 1
0 1 1
0 0 1

答案为
1 2 3
0 1 2
0 0 1

Solution

// 我的代码

class Solution {
public:
    vector<vector<int>> nearestZero(vector<vector<int>>& matrix) {
        int h=matrix.size(), w=matrix[0].size();
        vector<vector<int>> dp(h,vector<int>(w,INT_MAX));
        for(int times=0;times<=1;times++) // two passes, first forward then backward
            for(int i=times?h-1:0;times?i>=0:ifor(int j=times?w-1:0;times?j>=0:jif(matrix[i][j]==0)
                            dp[i][j]=0;
                        else {
                            if(i&&dp[i-1][j]!=INT_MAX&&dp[i][j]>dp[i-1][j]+1) // look up
                                dp[i][j]=dp[i-1][j]+1;
                            if(j&&dp[i][j-1]!=INT_MAX&&dp[i][j]>dp[i][j-1]+1) // look left
                                dp[i][j]=dp[i][j-1]+1;
                            if(i1&&dp[i+1][j]!=INT_MAX&&dp[i][j]>dp[i+1][j]+1) // look down
                                dp[i][j]=dp[i+1][j]+1;
                            if(j1&&dp[i][j+1]!=INT_MAX&&dp[i][j]>dp[i][j+1]+1) // look right
                                dp[i][j]=dp[i][j+1]+1;
                        }
        return dp;       
    }
}; 
//老师代码

class Solution {
public:
    vector< vector<int> > nearestZero(vector< vector<int> >& A) {
        vector< vector<int> > ans;
        queue< pair<int, int> > Q;
        const int D[4][2] = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}};
        int n, m, row, col, i, j;
        pair<int, int> u;
        n = A.size();
        m = A[0].size();
        ans.resize(n);
        for (i=0; ifor (i=0; ifor (j=0; jif (A[i][j] == 0) {
                    Q.push(make_pair(i, j));
                    ans[i][j] = 0;
                }
                else ans[i][j] = -1;
        while (!Q.empty()) {
            u = Q.front();
            Q.pop();
            for (i=0; i<4; i++) {
                row = u.first + D[i][0];
                col = u.second + D[i][1];
                if (row >= 0 && row < n && col >= 0 && col < m && ans[row][col] == -1) {
                    ans[row][col] = ans[u.first][u.second] + 1;
                    Q.push(make_pair(row, col));
                }
            }
        }       
        return ans;
    }
};

1004. 拓扑序[Special judge]

Description

在图论中,拓扑序(Topological Sorting)是一个有向无环图(DAG, Directed Acyclic Graph)的所有顶点的线性序列. 且该序列必须满足下面两个条件:

  1. 每个顶点出现且只出现一次.
  2. 若存在一条从顶点 A 到顶点 B 的路径,那么在序列中顶点 A 出现在顶点 B 的前面.

对于一个含有n个节点的有向无环图(节点编号0到n-1),输出它的一个拓扑序.

图的节点数和边数均不多于100000,保证输入的图是一个无环图.

例1:
n = 3,edges = {(0, 1), (0, 2)},函数应返回{0, 1, 2}或者{0, 2, 1}.

例2:
n = 4,edges = {(0, 1), (0, 2), (1, 2), (3, 0)},函数应返回{3, 0, 1, 2}.

Solution

//老师代码

class Solution {
private:
    vector< vector<int> > V;
    vector<int> ans;
    vector<bool> vis;
    void dfs(int u)
    {
        int v, i;
        vis[u] = true;
        for (i=0; iif (!vis[v]) dfs(v);
        }
        ans.push_back(u);
    }
public:
    vector<int> topologicalSort(int n, vector< pair<int, int> >& edges) {
        int u, v, i;
        V.resize(n);
        vis.resize(n);
        for (i=0; ifor (i=0; ifalse;
        for (i=0; iif (!vis[i]) dfs(i);
        return ans;
    }
};

1005. 最小和

Description

从数列A[0], A[1], A[2], …, A[N-1]中选若干个数,要求对于每个 i(0<=i< N-1),A[i]和A[i+1]至少选一个数,求能选出的最小和.

1 <= N <= 100000, 1 <= A[i] <= 1000

例1:A = {2, 5, 2},答案为4.
例2:A = {2, 5, 4},答案为5.

Solution

//老师代码

class Solution {
private:
    vector<int> f[2];   
public:
    int minSum(vector<int>& A) {
        int n, i;
        n = A.size();
        if (n == 0) return 0;
        f[0].resize(n);
        f[1].resize(n);
        f[0][0] = 0;
        f[1][0] = A[0];
        for (i=1; i0][i] = f[1][i-1];
            f[1][i] = A[i] + min(f[0][i-1], f[1][i-1]);
        }
        return min(f[0][n-1], f[1][n-1]);
    }
};

1006. 最长公共子串

Description

给定两个字符串 x=x­1x2x­ny=y­1y­2ym , 请找出x和y的最长公共子串的长度,也就是求出一个最大的k,使得存在下标i和j有 x­ix­i+1x­i+k1=yjy­j+1yj+k1 .

x和y只含有小写字母,长度均在1和1000之间.

例1:x = “abcd”, y = “cdef”,返回值为2.
例2:x = “abcabc”, y = “xyz”,返回值为0.
例3:x = “introduction”, y = “introductive”,返回值为10.

Solution

// 我的代码

class Solution {
public:
    int longestSubstring(string x, string y) {
        int len1 = x.length();  
        int len2 = y.length();  
        int result = 0;
        vector<vector<int>> c(len1+1, vector<int>(len2+1,0));

        for (int i = 0; i <= len1; i++) {  
            for( int j = 0; j <= len2; j++) {  
                if(i == 0 || j == 0) {  
                    c[i][j] = 0;  
                } else if (x[i-1] == y[j-1]) {  
                    c[i][j] = c[i-1][j-1] + 1;  
                    result = max(c[i][j], result);  
                } else {  
                    c[i][j] = 0;  
                }  
            }  
        }  
        return result;
    }
};    
//老师代码

class Solution {
private:
    vector< vector<int> > f;
public:
    int longestSubstring(string x, string y) {
        int res, n, m, i, j;
        n = x.length();
        m = y.length();
        f.resize(n + 1);
        for (i=0; i<=n; i++) f[i].resize(m + 1);
        res = 0;
        for (i=0; i<=n; i++)
            for (j=0; j<=m; j++) {
                if (i == 0 || j == 0 || x[i-1] != y[j-1]) f[i][j] = 0;
                else f[i][j] = f[i-1][j-1] + 1;
                if (f[i][j] > res) res = f[i][j];
            }
        return res; 
    }
};

1007. 怪兽训练

Description

贝爷的人生乐趣之一就是约战马会长. 他知道马会长喜欢和怪兽对决,于是他训练了N只怪兽,并对怪兽用0到N-1的整数进行编号. 贝爷训练怪兽的方式是让它们一对一互殴. 两只怪兽互殴会发生以下三种可能的结果:
1) 什么事也没发生
2) 第一只怪兽永远消失
3) 第二只怪兽永远消失
怪兽们经过了旷日持久的互殴. 贝爷不知道哪些怪兽进行了互殴也不知道它们互殴的顺序,但他确信无论经过多少次互殴,总有一些怪兽能存活下来,他将要派这些怪兽去和马会长对决. 现在他想知道至少有多少只怪兽能存活下来,你能帮他算出来吗?

请实现下面Solution类中的minLeftMonsters函数,完成上述功能.
参数G: N*N(1 <= N <= 50)字符矩阵,G[i][j]表示怪兽i和怪兽j互殴会发生的结果. 字符‘+’代表怪兽i会消失,’-’代表怪兽j会消失,数字’0’则代表什么都没发生. 输入保证G[i][i]一定是’0’,而且G[i][j]和G[j][i]一定相反(’-’和’+’互为相反,’0’和自身相反).

返回值:怪兽存活的最少数目.

class Solution {
public:
       int minLeftMonsters(vector<vector<char>> G) {

}
};

例1:
G =
0+-
-0+
+-0
返回1.

例2:
G =
000
000
000
返回3.

Solution

//老师代码

class Solution {
private:
    vector<int> pre, lowlink, sccno;
    stack<int> S;
    vector< vector<int> > V;
    vector<bool> vis;
    int dfs_clock, scc_cnt;
    void dfs(int u)
    {
        pre[u] = lowlink[u] = ++ dfs_clock;
        S.push(u);
        for (int i=0; iint v = V[u][i];
            if (!pre[v])
            {
                dfs(v);
                lowlink[u] = min(lowlink[u], lowlink[v]);
            }
            else if (!sccno[v]) lowlink[u] = min(lowlink[u], pre[v]);
        }
        if (lowlink[u] == pre[u])
        {
            scc_cnt ++;
            for (;;)
            {
                int x = S.top();
                S.pop();
                sccno[x] = scc_cnt;
                if (x == u) break;
            }
        }
    }
    void find_scc(int n)
    {
        dfs_clock = scc_cnt = 0;
        for (int i=0; i0;
        for (int i=0; iif (!pre[i]) dfs(i);
    }
public:
    int minLeftMonsters(vector< vector<char> > G) {
        int res, n, x, i, j;
        n = G.size();
        V.resize(n);
        pre.resize(n);
        lowlink.resize(n);
        sccno.resize(n);
        vis.resize(n + 1);
        for (i=0; ifor (j=0; jif (G[i][j] == '-') V[i].push_back(j);
        find_scc(n);
        for (i=1; i<=scc_cnt; i++) vis[i] = false;
        res = scc_cnt;
        for (i=0; ifor (j=0; jif (x == sccno[i]) continue;
                if (!vis[x])
                {
                    res --;
                    vis[x] = true;
                }
            }
        for (i=0; iwhile (!S.empty()) S.pop();
        return res; 
    }
}; 

你可能感兴趣的:(数据结构与算法)