去哪儿网2018春招软件开发工程师、前端开发工程师编程题 - 题解

不难,都是常规的操作,故题解写得简单点。

软件开发工程师编程题

第一题:在字典中找自己的逆序

题目

有一个单词列表,一个初始单词,初始单词需要通过单词列表逐步变换得到自己的逆序,求变换所需的最短变换路径长度。
变换规则:每次只能变动1个字母,每次变换只能从单词列表中选取。
例如:初始单词hot,其逆序为toh,单词列表[doh, got, dot, god, tod, dog, lot, log],最短变换路径为[hot,tod,doh,toh],最短变换路径长度为4
:单词列表中可包含最终单词,也可不包含最终单词,只要能够从字典中转换出最终单次即逆序初始单词即可,同时不包含初始单词;列表中每一项单词长度与初始单词相同;列表中单词不重复;所有字母均为小写。转换的最大次数为99次,转换不了输出0

解析

B F S 就可以搞定,把逆序后的结果要添加进单词列表中,不管单词列表中之前有没有这个结果,即使有也不会影响结果。

代码

#include <bits/stdc++.h>

using namespace std;

int main()
{
    string src, des;
    cin >> src;
    des = src;
    reverse(des.begin(), des.end());
    vector<string> arr;
    for (string str; cin >> str; arr.push_back(str)) {}
    arr.push_back(des);
    queue<pair<string, int> > que;
    que.emplace(src, 1);
    bool isOk = false;
    while (!que.empty()) {
        auto now = que.front();
        que.pop();

        if (now.first == des) {
            cout << now.second << endl;
            isOk = true;
            break;
        }

        if (now.second > 99)
            continue;
        for (auto it = arr.begin(); it != arr.end(); ++it) {
            int sum = 0;
            for (int i = 0; i < (int)now.first.size(); i++)
                sum += now.first[i] != (*it)[i];
            if (sum == 1)
                que.emplace(*it, now.second + 1);
        }
    }
    if (!isOk)
        puts("0");
    return 0;

}

第二题:包机商卖机票

题目

包机切位是去哪儿网机票事业部非常重要的机票售卖方式,通常一架飞机如果航司的收益管理人员没有信心将绝大多数坐位卖出去,那么就会依靠类似去哪儿网的旅行平台或者旅行社分别承包一部分坐位来销售,航司销售人员则借此降低了航线亏损风险。如果n家包机商中的i家恰好将飞机的m个坐位全部承包完,没有任何多余或者不足,则是一次完美的包机切位,输出 perfect,否则就不够完美,输出 good,航司还需要自己销售一部分座位。

解析

二进制枚举集合,先把大于m的元素去掉,然后枚举就好了,这里最好不要用背包的解法,因为元素的值可能很大,有可能会爆内存;或者你用递归枚举集合也行。

代码

import java.util.*;

public class Main {

    public Scanner cin = new Scanner(System.in);

    Main() {
        while (cin.hasNext()) {
            int n = cin.nextInt(), m = cin.nextInt();
            boolean isOk = false;
            ArrayList<Integer> arr = new ArrayList<Integer>();
            for (int i = 0, x; i < n; i++)
                if ((x = cin.nextInt()) <= m)
                    arr.add(x);
            for (int i = 0; i < (1 << arr.size()); i++) {
                int sum = 0;
                for (int bit = 0; bit < arr.size(); bit++)
                if ((i & (1 << bit)) != 0)
                    sum += arr.get(bit);
                if (sum == m) {
                    isOk = true;
                    break;
                }
            }
            System.out.println(isOk ? "perfect" : "good");
        }
    }

    public static void main(String[] args) {
        new Main();
    }
}

开发工程师编程题

第一题,大家应该都会。

第二题:网络连通性检查

题目

一个网络有N个节点(编号为0 ~ N-1)和M条路,管理员会让你检查一些节点间是否联通

解析

并查集入门题,先根据给出的图建立并查集,然后在询问中看看两个节点的父亲是否一样就行了。

代码

#include <bits/stdc++.h>

using namespace std;

#define MAX_LINE 1005

int p[MAX_LINE];

int find(int x)
{
    return x == p[x] ? x : (p[x] = find(p[x]));
}

int main()
{
    for (int n, m, q; cin >> n >> m; ) {
        for (int i = 0; i < n; p[i] = i, ++i) {}
        for (int i = 0, x, y; i < m; i++) {
            cin >> x >> y;
            int fa = find(x), fb = find(y);
            if (fa != fb)
                p[fb] = fa;
        }
        int ans = 0;
        cin >> q;
        for (int x, y; q--; ) {
            cin >> x >> y;
            if (find(x) == find(y))
                ++ans;
        }
        cout << ans << endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/FlushHip/article/details/79792857