招商银行信用卡中心2019秋招IT笔试(AI、开发、测试开发方向)第一批

版权声明:本文为博主原创文章,禁止转载。 https://blog.csdn.net/FlushHip/article/details/84137906

鸡鸭分类问题

题目

农场有n只鸡鸭排为一个队伍,鸡用“C”表示,鸭用“D”表示。当鸡鸭挨着时会产生矛盾。需要对所排的队伍进行调整,使鸡鸭各在一边。每次调整只能让相邻的鸡和鸭交换位置,现在需要尽快完成队伍调整,你需要计算出最少需要调整多少次可以让上述情况最少。例如:CCDCC->CCCDC->CCCCD这样就能使之前的两处鸡鸭相邻变为一处鸡鸭相邻,需要调整队形两次。

输入描述:

输入一个长度为N,且只包含CD的非空字符串。

输出描述:

使得最后仅有一对鸡鸭相邻,最少的交换次数

样例:

CCDCC
>--------------------------------------------------<
2

解析

枚举两种最终状态,CDCCC,要么变成DCCCC,要么变成CCCCD

对于其中任意一种状态的每一个需要移动的元素,只需要看一下移动的方向上有多少个不一样的元素,然后累加起来就行了。

#include <bits/stdc++.h>

int main()
{
    for (std::string str; std::cin >> str; ) {
        std::vector<int> c(str.size(), 0), d(c);
        for (unsigned i = 0; i < c.size(); c[i] = (str[i] == 'C') + (i ? c[i - 1] : 0), ++i) {}
        for (unsigned i = 0; i < d.size(); d[i] = (str[i] == 'D') + (i ? d[i - 1] : 0), ++i) {}
        int ansC = 0, ansD = 0;
        for (unsigned i = 0; i < c.size(); ansC += str[i] == 'D' ? c[i] : 0, ++i) {}
        for (unsigned i = 0; i < d.size(); ansD += str[i] == 'C' ? d[i] : 0, ++i) {}
        std::cout << std::min(ansC, ansD) << std::endl;
    }
    return 0;
}

比特币最佳买卖时机

题目

给定一个正整数数组,它的第 i 个元素是比特币第 i天的价格。

如果你最多只允许完成一笔交易(即买入和卖出一次),设计一个算法来计算你所能获取的最大利润。

注意你不能在买入比特币前卖出。

输入描述:

正整数数组,为以空格分隔的n个正整数

输出描述:

最大利润

样例:

7 1 5 3 6 4
>--------------------------------------------------<
5

解析

在序列中找到一个差值最大的有序偶 { ( a i , a j ) i &lt; j , a i &lt; = a j } \{(a_i, a_j) | i &lt; j , a_i &lt;= a_j\}

O ( n 2 ) O(n^2) 的做法应该都会。这里讲一下 O ( n ) O(n)的做法

对于第i个位置上的元素,我们只需要知道区间[0, i - 1]最小值,就可以得出第二个数的位置为i的最大差值有序偶,枚举i就可以得出答案;而区间[0, i - 1]最小值可以预处理出来。

因此总体时间复杂度为 O ( n ) O(n)

#include <bits/stdc++.h>

int main()
{
    std::string arrString;
    std::getline(std::cin, arrString);
    std::vector<int> arr, dp;
    std::stringstream sin(arrString);
    for (int x; sin >> x; arr.emplace_back(x)) {}
    dp.resize(arr.size(), arr[0]);
    for (unsigned i = 1; i < dp.size(); dp[i] = std::min(dp[i - 1], arr[i]), ++i) {}
    int ans = 0;
    for (unsigned i = dp.size() - 1; i > 0; ans = std::max(ans, arr[i] - dp[i - 1]), --i) {}
    std::cout << ans << std::endl;
    return 0;
}

爱吃喵粮的小招喵

题目

小招喵喜欢吃喵粮。这里有 N 堆喵粮,第 i 堆中有 p[i] 粒喵粮。喵主人离开了,将在 H 小时后回来。

小招喵可以决定她吃喵粮的速度 K (单位:粒/小时)。每个小时,她将会选择一堆喵粮,从中吃掉 K 粒。如果这堆喵粮少于 K 粒,她将吃掉这堆的所有喵粮,然后这一小时内不会再吃更多的喵粮。

小招喵喜欢慢慢吃,但仍然想在喵主人回来前吃掉所有的喵粮。

返回她可以在 H 小时内吃掉所有喵粮的最小速度 KK 为整数)。

输入描述:

第一行输入为喵粮数组,以空格分隔的N个整数

第二行输入为H小时数

输出描述:

最小速度K

样例:

3 6 7 11 8
>--------------------------------------------------<
4

解析

二分答案,求下界。

要注意的是,H一定大于N,不然,多快的速度都不可能完成任务。题目中没有说明,这里应该强调一下。

#include <bits/stdc++.h>

int main()
{
    std::string pString;
    std::getline(std::cin, pString);
    int H;
    std::cin >> H;
    std::vector<int> p;
    [] (const std::string & str, std::vector<int> & vec) {
        std::stringstream sin(str);
        for (int x; sin >> x; vec.emplace_back(x)) {}
    } (pString, p);

    int l = 1, r = *std::max_element(std::begin(p), std::end(p));
    while (l < r) {
        int mid = l + (r - l) / 2;
        if ([&] (int k) {
            return std::accumulate(std::begin(p), std::end(p), 0, [k] (int init, int s) {
                return init + std::ceil(s * 1.0 / k);
            }) <= H;
        } (mid))
            r = mid;
        else
            l = mid + 1;
    }
    std::cout << l << std::endl;
    return 0;
}

推倒吧骨牌

题目

有一排长度为N的骨牌,初始状态下所有的骨牌都是站立状态,如下图所示。
在这里插入图片描述
现在我们选定其中几块骨牌,并指定其方向进行推倒,如下图所示。
在这里插入图片描述
如果用字符的形式定义,则上述过程可以描述为:
在这里插入图片描述
输入".L.R...LR....L.",对应的输出为"LL.RR.LLRRRLLL."
其中L表示向左倒,R表示向右倒,.表示任然为站立状态。

输入描述:

输入为一个长度不超过1000的,仅包含‘L’‘R’‘.’的字符串

输出描述:

根据输入,输出一个仅由‘L’‘R’‘.’组成的结果字符串

样例:

.L.R...LR....L.
>--------------------------------------------------<
LL.RR.LLRRRLLL.

解析

模拟就好了,只有R...L这种情况会往中间挤,处理下就行了。

#include <bits/stdc++.h>

int main()
{
    for (std::string str; std::cin >> str; ) {
        bool LorR = false;
        std::string::iterator pos = std::begin(str), pre = pos;
        for (;;) {
            auto it = std::find_if(pre, std::end(str), [] (const char c) {
                return c == 'R' || c == 'L';
            });
            if (it == std::end(str))
                break;
            if (*it == 'R') {
                if (LorR) std::fill(pos, it, 'R');
                LorR = true;
                pos = it;
            } else {
                if (LorR) {
                    std::fill(pos + 1, pos + (it - pos + 1) / 2, 'R');
                    std::fill(pos + (it - pos + 1) / 2, it, 'L');
                    if ((it - pos - 1) & 1) *(pos + (it - pos) / 2) = '.';
                    LorR = false;
                } else {
                   std::fill(pre, it, 'L');
                }
            }
            pre = it + 1;
        }
        if (LorR) std::fill(pos, std::end(str), 'R');
        std::cout << str << std::endl;
    }
    return 0;
}

重叠的装饰

题目

我们部门需要装饰墙,但是墙非常非常的长,有一千万米。我们会按顺序贴很多海报在上面,这些海报相互之间会重叠,请问下,最后还能看到哪些?(只看到一部分也算)

输入描述:

N表示N张海报

接下来每一行代表海报的左右边界(上下默认全满),LiRi,均为整数,大于0,小于一千万。海报按输入顺序张贴。

输出描述:

有多少张海报是可见的

样例:

5
1 4
2 6
8 10
3 4
7 10
>--------------------------------------------------<
4

解析

不考虑数据范围,模拟就可以了;

数据范围一大,就需要一些技巧来模拟,这里用到的技巧是线段树维护区间更新加上区间离散化。

其实这个题是POJ - 2528原题。

但是,这个题的数据不对,只能过80%的数据,我把网上其他大牛的代码交了下也是只能过80%的数据,而且,不过的那组数据我弄下来看看,也不对劲。

所以,我写的下面这个代码可能过不了这个题,但是确实是正确的。

#include <bits/stdc++.h>

struct SegmentTree;
typedef struct std::shared_ptr<SegmentTree> pSegmentTree;

struct SegmentTree
{
public:
    void update(int lhs, int rhs, int l, int r, int c);
    unsigned query(int lhs, int rhs);

    static void build(pSegmentTree & root, int lhs, int rhs);

public:
    pSegmentTree lchs = nullptr, rchs = nullptr;
    int color = 0;

private:
    void query_aux(int lhs, int rhs, std::set<int> & colors);
};

void SegmentTree::build(pSegmentTree & root, int lhs, int rhs)
{
    root = std::make_shared<SegmentTree>();

    if (lhs == rhs) return ;

    int mid = (lhs + rhs) >> 1;
    build(root->lchs, lhs, mid);
    build(root->rchs, mid + 1, rhs);
}

void SegmentTree::update(int lhs, int rhs, int l, int r, int c)
{
    if (lhs == l && rhs == r) {
        color = c;
        return ;
    }

    if (color) {
        if (lchs) lchs->color = color;
        if (rchs) rchs->color = color;
        color = 0;
    }

    int mid = (lhs + rhs) >> 1;
    if (r <= mid) lchs->update(lhs, mid, l, r, c);
    else if (mid + 1 <= l) rchs->update(mid + 1, rhs, l, r, c);
    else {
        lchs->update(lhs, mid, l, mid, c);
        rchs->update(mid + 1, rhs, mid + 1, r, c);
    }
}

unsigned SegmentTree::query(int lhs, int rhs)
{
    std::set<int> colors;
    query_aux(lhs, rhs, colors);
    return colors.size();
}

void SegmentTree::query_aux(int lhs, int rhs, std::set<int> &colors)
{
    if (color) {
        colors.insert(color);
        return ;
    }
    if (lhs == rhs) return ;
    int mid = (lhs + rhs) >> 1;
    lchs->query_aux(lhs, mid, colors);
    rchs->query_aux(mid + 1, rhs, colors);
}

int main()
{
    for (int n; EOF != std::scanf("%d", &n); ) {
        typedef std::pair<int, int> Line;
        std::vector<Line> lines;
        for (int i = 0, x, y; i < n; std::scanf("%d%d", &x, &y), lines.emplace_back(x, y), ++i) {}
        std::vector<int> digits;
        for (int i = 0; i < n; digits.emplace_back(lines[i].first), digits.emplace_back(lines[i].second), ++i) {}
        std::sort(std::begin(digits), std::end(digits));
        for (unsigned i = 1, top = digits.size(); i < top; ++i) if (digits[i] - digits[i - 1] > 1)
            digits.emplace_back(digits[i] - 1);
        std::sort(std::begin(digits), std::end(digits));
        digits.erase(std::unique(std::begin(digits), std::end(digits)), std::end(digits));

        std::shared_ptr<SegmentTree> root = nullptr;
        SegmentTree::build(root, 1, (int)digits.size());
        for (const auto & line : lines) {
            static int color = 1;
            root->update(1, (int)digits.size(),
                std::lower_bound(std::begin(digits), std::end(digits), line.first) - std::begin(digits) + 1,
                std::lower_bound(std::begin(digits), std::end(digits), line.second) - std::begin(digits) + 1,
                color++);
        }
        std::printf("%u\n", root->query(1, (int)digits.size()));
    }
    return 0;
}

猜你喜欢

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