sicily考试模拟题-1003相连的1 1004isDAG? 1005相邻的数 1006单词变换

1003相连的1


题目描述

对于一个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.

解题思路

考查BFS,通过BFS寻找一个点所连接的所有点,queue记录同一层的节点。

解题代码

#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;




class Node{
  public:
    int x;
    int y;
    Node(int i,int j){x=i;y=j;}
};


class Solution {
public:

  //定义四个方向
  int dir[4][2]={  {0, 1}, {1, 0},  {0, -1}, {-1, 0}  };  



  bool isValid(vector<std::vector<char> >&A,Node &node){
    int m=A.size();
    int n=A[0].size();

    if (node.x<0 || node.x>=m ) return false;
    if (node.y<0 || node.y>=n ) return false;
    if (A[node.x][node.y]!='1') return false;

    return true;
  }


  void BFS(vector<vector<char> >&A,vector<vector<bool> >&B,Node &node){
    queue<Node>que;
    que.push(node);
    B[node.x][node.y]=true;

    while(!que.empty()){
      Node p = que.front();
      que.pop();
      for (int i = 0; i < 4; ++i)
      {
        Node pNext=Node(p.x+dir[i][0],p.y+dir[i][1]);

        // if (Vw == Vd){//找到终点了!  
     //              //把路径记录,这里没给出解法  
     //              return true;//返回  
    //          }  

        if (isValid(A,pNext)&&B[pNext.x][pNext.y]==false ){
          que.push(pNext);
          B[pNext.x][pNext.y]=true;
        }
      }
    }
  }


    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<std::vector<bool> > B(m,std::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 ++;
              Node node=Node(i,j);
              BFS(A,B,node);
            }
          }
         }

         return count;
      }

};

int main()
{

   vector<vector<char> >migong(3,vector<char>(4));


    migong[0][0]='1';migong[0][1]='1';migong[0][2]='0';migong[0][3]='1';
    migong[1][0]='0';migong[1][1]='1';migong[1][2]='0';migong[1][3]='1';
    migong[2][0]='1';migong[2][1]='1';migong[2][2]='1';migong[2][3]='0';



   Solution sol;
   int res=sol.countConnectedOnes(migong);
   cout << "result is ->"<<res << endl; 

   return 0;
}

1004 isDAG?


题目描述

在图论中,如果一个有向图从任意顶点出发无法经过若干条边回到该点,则这个图是一个有向无环图(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函数的代码. 注意不要修改类和函数的名称.

解题思路

先建立图的vector结构,再dfs检索有向图中有没有环

解题代码



class Solution {
public:
    bool isDAG(int n, vector<pair<int, int>>& edges) {
      //构造图向量-有向图
      std::vector< std::vector<int> > graph(n);
      for (int i = 0; i < edges.size(); ++i)
      {
        graph[edges[i].first].push_back(edges[i].second);
      }

      //记录已访问节点
      std::vector<bool> visited(n,false);
      //记录当前路径上的节点
      std::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(std::vector<std::vector<int> > &graph, int node,std::vector<bool> &visited,std::vector<bool> &onpath ){
      if (visited[node]) return false;
      onpath[node]=visited[node]=true;
      for (int i = 0; i < graph[node].size(); ++i)
      {
        //onpath是指向路径上的节点--回路;has_circle是dfs思想
        if(onpath[ graph[node][i] ]|| has_circle(graph,graph[node][i],visited,onpath) )
          return true;
      }
      onpath[node]=false;
      return false;

    }

};


1005相邻的数


题目描述

从数列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.

解题思路

动态规划题目,写出状态转移方程即可

解题代码

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

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


int main(int argc, char const *argv[])
{
    Solution sol;

    cout<<"-------------------------------------------"<<endl;
    int arr1[]={2,5,2}; int arr2[]={2,5,4}; 
    vector<int>A(begin(arr1),end(arr1));
    vector<int>B(begin(arr2),end(arr2));
    cout<<"solutionA is :"<<sol.maxSum(A)<<endl;
    cout<<"solutionB is :"<<sol.maxSum(B)<<endl;
    // cout<<"solution is :"<<sol.F(2,3)<<endl;
    // cout<<"solution is :"<<sol.F(10,10)<<endl;

    cout<<"-------------------------------------------"<<endl;
    return 0;
}

1006单词变换


题目描述

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

解题思路

经典动规。
使用一个二维数组dp[m][n] 来维护状态,它表示从一个长度为m的word1变换到一个长度为n的word2所需要的最少操作数。
每次将两个单词往前看一个字母,那么有如下两种可能。

两个字母相同。那么,显然不需要做更改操作,有 dp[m][n] = dp[m - 1][n - 1]
两个字母不相同,那么,需要考虑如下三种操作:
如果word1的当前字母和word2的前一个字母相同,那么说明word1需要做1次插入操作,即dp[m][n] = 1 + dp[m][n - 1];
如果word1的前一个字母和word2的当前字母相同,那么说明word1需要做1次删除操作,即dp[m][n] = 1 + dp[m - 1][n];
如果word1的前一个字母和word2的前一个字母相同,那么说明word1需要做1次替换操作,即dp[m][n] = 1 + dp[m - 1][n].
由于要找的是最小的操作次数,所以,在第二种情况下,取三种子情况的最小值。

解题代码

class Solution {
public:
int triMin(int a, int b, int c) {
int tempA = min(a, b);
int tempB = min(b, c);
return min(tempA, tempB);
}

int minDistance(string word1, string word2) {
    int m = word1.size();
    int n = word2.size();
    int dp[m + 1][n + 1];

    for (int i = 0; i <= m; ++i) {
        for (int j = 0; j <= n; ++j) {
            if (i == 0) dp[i][j] = j;
            else if (j == 0) dp[i][j] = i;
            else if (word1[i - 1] == word2[j - 1])
                dp[i][j] = dp[i - 1][j - 1];
            else 
                dp[i][j] = 1 + triMin(dp[i][j - 1],     // insert
                                   dp[i - 1][j],     // remove
                                   dp[i - 1][j - 1]); // replace            
        }
    }

    return dp[m][n];   
}

};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值