2017滴滴实习招聘笔试两道编程题

一、岛屿问题

有n*m的二维的地图,其中‘1’表示陆地,‘0’表示海水,相邻的陆地可以组成更大的陆地,现在需要统计出岛屿的个数。岛屿是被横向、纵向海水环绕的(斜向的陆地不连接),地图的四边都是海水围绕。

输入描述:

每个测试输入的第一行包括两个整数n和m.(1< n, m <10)

输出描述:

计算出符合岛屿规则的个数

输入例子:

4 5
11000
11000
00100
00011

输出例子:

3

解题思路:

要找总共有多少个岛屿,必须要把n*m的地图上的所有点都遍历一遍,因为每个点都有可能所在是一块新的岛屿。当给定一个起始点时需要判断这个起始点所在的岛屿上都有哪些点,这里需要用一个n*m的标记数组来记录是否当前点已经判断过在某个岛屿上了,避免错误判断为其他岛屿上了。问题就只需要考虑如何从一个起始点判断岛屿上有哪些点了,这个可以采用深度优先遍历DFS或者广度优先遍历BFS,注意要考虑上下左右四个方向。

代码(采用BFS):

#include <iostream>
    #include <string>
    #include <queue>
    using namespace std;

    void island(bool **a, int n, int m, bool **flag, int i, int j){
        queue<pair<int, int> > qu;
        qu.push(make_pair(i,j));
        flag[i][j] = 1;
        while(!qu.empty()){
            pair<int, int> p = qu.front();
            qu.pop();
            if(p.second+1 < m && a[p.first][p.second+1] == 1 && flag[p.first][p.second+1] == 0 ){
                qu.push(make_pair(p.first, p.second+1));
                flag[p.first][p.second+1] = 1;
            }
            if(p.first+1 < n && a[p.first+1][p.second] == 1 && flag[p.first+1][p.second] == 0){
                qu.push(make_pair(p.first+1,p.second));
                flag[p.first+1][p.second] = 1;
            }
            if(p.second-1 >=0 && a[p.first][p.second-1] == 1 && flag[p.first][p.second-1] == 0){
                qu.push(make_pair(p.first,p.second-1));
                flag[p.first][p.second-1] = 1;
            }
            if(p.first-1 >= 0 && a[p.first-1][p.second] == 1 && flag[p.first-1][p.second] == 0){
                qu.push(make_pair(p.first-1,p.second));
                flag[p.first-1][p.second] = 1;
            }
        }
    }

    void test1(){
        int n, m;
        while(cin >> n >> m){
            bool **a = new bool*[n];
            bool **flag = new bool*[n];
            for(int i = 0;i < n;i++){
                a[i] = new bool[m];
                flag[i] = new bool[m];
            } 
            string temp;
            for(int i = 0; i < n; i++){
                cin >> temp;
                for(int j = 0; j < m; j++){
                    a[i][j] = temp[j]-'0';
                    flag[i][j] = 0;
                }
            }
            int count = 0;
            for(int i = 0; i < n; i++){
                for(int j = 0; j < m; j++){
                    if(a[i][j] == 1 && flag[i][j] == 0){
                        count++;
                        island(a, n, m, flag, i, j);
                    }
                }
            }
            cout << count << endl;
            for(int i = 0; i < n; i++){
                delete [] a[i];
                delete [] flag[i];
                a[i] = 0;
                flag[i] = 0;
            }
            delete [] a;
            delete [] flag;
            a = 0;
            flag = 0;
        }
    }

    int main(){
        test1();
        return 0;
    } 

测试通过,这里提供一个复杂一点的测试用例:

输入:

6 9
100111101
010001000
011111000
000001011
000001110
110000000

输出:

5

二、九宫格输入法找单词问题

根据T9键盘的数字和英文对应关系,输入对应的三个数字,求出最相似的单词。
{‘2’:”abc”,’3’:”def”, ‘4’:”ghi”, ‘5’:”jkl”, ‘6’:”mno”, ‘7’:”pqrs”, ‘8’:”tuv”, ‘9’:”wxyz”}
两个串的相似度定义为他们的最长公共子序列长度。

输入描述:

输入的第一行为字典,里面包含若干备选单词。
第二行为输入的数字。

输出描述:

根据T9键盘的对应关系,求出字典的最相似的单词。

输入例子:

Produces a prinable string representation of a dictionary
784

输出例子:

string

解题思路:

首先肯定要保存从数字键到字母的映射的,这个直接用一维数组保存就好。根据给定的测试用例,比如输入784,7对应可能是pqrs,8对应可能是tuv,4对应可能是ghi,从784中各选取一个字符组成一个字符串,比如ptg、pth、pti等等,然后将这三个字符组成的字符串和输入的字符串中每个单词计算最长公共子序列,找到最相似的单词,返回结果。一般而言查找字符串最长公共子序列是采用动态规划的算法,在下面代码中用maxCommonSequence_better函数计算,但是这道题题目描述中给出了限制条件只输入对应的三个数字,所以难度变小,直接列出逻辑上可能存在的各种情况即可,下面代码中用maxCommonSequence函数计算。

(这道题笔试时没有时间做了,没有在笔试环境中测试,不知道我理解的意思对不对。)

代码:

#include <iostream>
    #include <string>
    #include <sstream>
    using namespace std;

    int maxCommonSequence_better(string word, string key){
        int m = key.length(), n = word.length();
        int dp[m+1][n+1]={0,0};
        for(int i = 0; i <= m; i++){
            for(int j = 0; j <= n; j++){
                dp[i][j] = 0;
            }
        }
        for(int i = 1; i <= m; i++){
            for(int j = 1; j <= n; j++){
                int index = word.substr(0,j).find_last_of(key[i-1]);
                if(index == -1){
                    dp[i][j] = dp[i-1][j];
                } else {
                    dp[i][j] = ((dp[i-1][index]+1) > dp[i-1][j])?(dp[i-1][index]+1):dp[i-1][j];
                }
            }
        }
        return dp[m][n];
    }

    int maxCommonSequence(string word, string key){
        int index1 = word.find_first_of(key[0]);
        if(index1 != -1){
            string second = word.substr(index1+1);
            int index2 = second.find_first_of(key[1]);
            if(index2 != -1){
                if(second.substr(index2+1).find_first_of(key[2]) != string::npos){
                    return 3;
                }
                return 2;
            }
            if(second.find_first_of(key[2]) != string::npos){
                return 2;
            }
            return 1;
        }
        int index3 = word.find_first_of(key[1]);
        if(index3 != -1){
            if(word.substr(index3+1).find_first_of(key[2]) != string::npos){
                return 2;
            }
            return 1;
        }
        if(word.find_first_of(key[2]) != string::npos){
            return 1;
        }
        return 0;
    }

    void test1(){
        string a[10] = {"", "","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
        string line;
        while(getline(cin, line)){
            string num;
            cin >> num;
            string s1 = a[num[0]-'0'];
            string s2 = a[num[1]-'0'];
            string s3 = a[num[2]-'0'];
            stringstream ss;
            ss << line;
            string word;
            string answer;
            int mostSimilar = 0;
            while(ss >> word){
                string key;
                for(int i=0; i < s1.length();i++){
                    key += s1[i];
                    for(int j=0;j < s2.length();j++){
                        key += s2[j];
                        for(int k=0;k < s3.length();k++){
                            key += s3[k];
                            int d = maxCommonSequence_better(word,key);
                            if(d > mostSimilar){
                                mostSimilar = d;
                                answer = word;
                            }
                            key = "";
                        }
                    }
                }
            } 
            cout << answer << endl;
        }   
    }

    void test2(){
        cout << maxCommonSequence_better("representation", "rtg") << endl;;
    }

    int main(){
        test1();
        //test2();
        return 0;
    }

通过测试用例。

如果有不对的地方,烦请在评论区指正。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值