算法机考模拟题 part2

  • 4 相连的1 题目描述

对于一个01矩阵A,求其中有多少片连成一片的1. 每个1可以和上下左右的1相连.
请为下面的Solution类实现解决这一问题的函数countConnectedOnes,函数参数A为给出的01矩阵,A的行数和列数均不大于1000. 函数的返回值是问题的答案.
例1:
A=
100
010
001
答案为3.
例2:
A=
1101
0101
1110
答案为2.
注意:你只需要提交Solution类的代码,你在本地可以编写main函数测试程序,但不需要提交main函数的代码. 注意不要修改类和函数的名称.

  • 4 分析
    该题是DFS的变形应用。

    • 4 代码
class Solution {
public:
void dfs(vector<vector<char> >& A,int m,int n,int i,int j){
    if(i<0 ||j<0 ||i>=m||j>=n)
        return;
    if(A[i][j]!='1')
        return;
    else{
        A[i][j]='2';
        dfs(A,m,n,i-1,j);
        dfs(A,m,n,i+1,j);
        dfs(A,m,n,i,j+1);
        dfs(A,m,n,i,j-1);
    }
}
int countConnectedOnes(vector<vector<char> >& A) {
    if(A.empty())
        return 0;
    int m=A.size();
    int n=A[0].size();
    int count=0;
    for(int i=0;i<m;i++)
        for(int j=0;j<n;j++)
            if(A[i][j]=='1'){
                count++;
                dfs(A,m,n,i,j);
            } 
    return count;
}
};  
  • 5 无环图 题目描述

在图论中,如果一个有向图从任意顶点出发无法经过若干条边回到该点,则这个图是一个有向无环图(Directed Acyclic Graph,DAG). 对于一个n个节点的有向图(节点编号从0到n-1),请判断其是否为有向无环图.
图的节点数和边数均不多于100000.
请为下面的Solution类实现解决上述问题的isDAG函数,函数参数中n为图的节点数,edges是边集,edges[i]表示第i条边从edges[i].first指向edge[i].second. 如果是有向无环图返回true,否则返回false.
例1:
n = 3,edges = {(0, 1), (0, 2)},函数应返回true.
例2:
n = 2,edges = {(0, 1), (1, 0)},函数应返回false.

  • 5 分析
    在我看来该题的关键是如何节省时耗。可以用拓扑排序,也可以使用DFS+回溯

  • 5 代码

class Solution {
public:
       bool isDAG(int n, vector<pair<int, int> >& edges) {
            if(edges.empty())
                return true;


            stack<int> zeroIn;  
            vector<int> in(n,0);
            vector<set<int> > mp(n);
            for(int i=0;i<edges.size();i++){
                in[edges[i].second]++;
                mp[edges[i].first].insert(edges[i].second);
            }

            for(int i=0;i<in.size();i++)
                if(in[i]==0)
                    zeroIn.push(i); 

            int delNum=0,first;
            while(!zeroIn.empty()){
                first=zeroIn.top();
                zeroIn.pop();
                delNum++;
                for(set<int>::iterator it = mp[first].begin(); it != mp[first].end(); ++it){
                    in[*it]--;
                    if(in[*it]==0)
                        zeroIn.push(*it);       
                }
            }
            if(delNum<n)
                return false;
            else
                return true;
        }       
}; 
  • 6 最大的和 题目描述

从数列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& A) {
}
};
例1:A = {2, 5, 2},答案为5.
例2:A = {2, 5, 4},答案为6.

  • 6 分析
    又是一个贪心的应用。

  • 6 代码
    形式1:

class Solution {
public:
    int maxSum(vector<int>& A) {
        if(A.empty())
            return 0;

        int curMax,lastMax1,lastMax2;
        for(int i=0;i<A.size();i++){
            if(i==0){
                lastMax2=A[0];
                curMax=A[0];
            }
            else if(i==1){
                lastMax1=A[0]>A[1]?A[0]:A[1];
                curMax=lastMax1;
            }
            else{
                curMax=lastMax2+A[i]>lastMax1? lastMax2+A[i]:lastMax1;
                lastMax2=lastMax1;
                lastMax1=curMax;
            }
        }
        return curMax;

    }

}; 

形式2

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];  
    }  
}; 
  • 7 单词变换 题目描述

对于两个只含有小写英文字母(’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.

  • 7 分析
    编辑距离的计算,动态规划的应用。用分治的方法会超时。

  • 7 代码

class Solution {
public:
    int minDistance(string word1, string word2) {
        int a=word1.size();
        int b=word2.size();
        vector<vector<int> > c(a+1, vector<int>(b+1));
        for(int i=0;i<a;i++)
            c[i][b]=a-i;
        for(int i=0;i<b;i++)
            c[a][i]=b-i;
        c[a][b]=0;
        for(int i=a-1;i>=0;i--)
            for(int j=b-1;j>=0;j--){
                if(word2[j]==word1[i])
                    c[i][j]=c[i+1][j+1]; 
                else
                    c[i][j]=minValue(c[i][j+1],c[i+1][j],c[i+1][j+1])+1;
            }
            return c[0][0];
       }


    int minValue(int t1,int t2,int t3){
        if(t1<t2){
            if(t1<t3)
                return t1;
            else
                return t3;
        }else{
            if(t2<t3)
                return t2;
            else 
                return t3;
        }

    }
};  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值