今日头条2018校招测试开发方向(第一、二、三、四批)编程题汇总 - 题解

对于今日头条这家公司来说,测试的题和后端开发的题几乎是一样的,但是由于第一批的后端开发的题没有在牛客网上放出来,因此,猜测后端开发第一批的题应该和后端开发第一批的题一样,同时也想做一个测试方向编程题的汇总。

原题链接:

今日头条2018校招测试开发方向(第一批)

第一题:编程题1

题目:

P为给定的二维平面整数点集。定义P 中某点x,如果x满足 P 中任意点都不在 x 的右上方区域内(横纵坐标都大于x),则称其为“最大的”。求出所有“最大的”点的集合。(所有点的横坐标和纵坐标都不重复, 坐标轴范围在[0, 1e9) 内)
 
如下图:实心点为满足条件的点的集合。请实现代码找到集合 P 中的所有 ”最大“ 点的集合并输出。
这里写图片描述
 
输入描述:
第一行输入点集的个数 N, 接下来 N行,每行两个数字代表点的 X 轴和 Y 轴。
对于 50%的数据, 1<=N<=10000 1 <= N <= 10000 ;
对于 100%的数据, 1<=N<=500000 1 <= N <= 500000 ;

解析:

抓住最大点的关键信息:在最大点的右上方没有其余点,这就意味着,如果当前点是最大点,那么在该点右边的所有点都比该点矮,这一点要理解,因为在该点左边的点无论如何都不会对该点是否为最大点有影响(原因看加粗字体);

先按X轴坐标从大到小排序(这是为了保证遍历过的点都在当前点的右边),然后依次遍历这些点,遍历的时候维护一个最大的Y轴坐标,这样子遍历到当前点时判断一下当前点的Y轴坐标是否大于最大的Y轴坐标,如果不大于,这说明在当前点的右上方有点,当前点就不是最大点;如果大于,那么说明当前点的右上方没有点,这个点就是最大点,同时更新最大的Y轴坐标。

时间复杂度: O(nlogn) O ( n l o g n )

代码:

#include <bits/stdc++.h>

using namespace std;

bool cmpFirst(const pair<int, int> &A, const pair<int, int> &B)
{
    return A.first > B.first;
}

int main()
{
    for (int n; EOF != scanf("%d", &n); ) {
        vector<pair<int, int> > arr;
        vector<int> tmpArr;
        for (int i = 0, x, y; i < n; i++)
            scanf("%d%d", &x, &y), arr.emplace_back(x, y), tmpArr.push_back(y);
        sort(arr.begin(), arr.end(), cmpFirst);

        vector<pair<int, int> > ans;
        for (int i = 0, theMax = 0; i < n; i++) {
            if (arr[i].second > theMax)
                ans.push_back(arr[i]), theMax = arr[i].second;
        }

        for (auto it = ans.rbegin(); it != ans.rend(); it++)
            printf("%d %d\n", it->first, it->second);
    }
    return 0;
}

第二题:编程题2

题目:

给定一个数组序列, 需要求选出一个区间, 使得该区间是所有区间中经过如下计算的值最大的一个:
区间中的最小数 * 区间所有数的和最后程序输出经过计算后的最大值即可,不需要输出具体的区间。如给定序列[6, 2, 1]则根据上述公式, 可得到所有可以选定各个区间的计算值:
 
[6] = 6 * 6 = 36;
[2] = 2 * 2 = 4;
[1] = 1 * 1 = 1;
[6,2] = 2 * 8 = 16;
[2,1] = 1 * 3 = 3;
[6, 2, 1] = 1 * 9 = 9;

 
从上述计算可见选定区间[6] ,计算值为 36, 则程序输出为 36。
区间内的所有数字都在[0, 100]的范围内;
 
输入描述:
第一行输入数组序列长度n,第二行输入数组序列。
对于 50%的数据, 1<=n<=10000 1 <= n <= 10000 ;
对于 100%的数据, 1<=n<=500000 1 <= n <= 500000 ;

解析:

先求出以当前点为最小值的最大子区间,这个可以用单调栈去求,如果还不清楚单调栈可以求这个东西,就要好好补补课了;然后预处理出前缀和;单调栈在入栈的时候能确定区间的左端点,而在出栈的时候能确定右端点,因此,在出栈的时候就维护一个最大值。这个最大值最后就是答案。

时间复杂度: O(n) O ( n )

代码:

#include <bits/stdc++.h>

using namespace std;

int main()
{
    for (int n; EOF != scanf("%d", &n); ) {
        vector<int> arr(n + 1, 0), sum(n + 1, 0);
        for (int i = 1, x; i <= n; ++i) {
            scanf("%d", &x);
            arr[i] = x;
            sum[i] = sum[i - 1] + x;
        }
        stack<pair<int, int> > st;
        int ans = 0;
        for (int i = 1; i <= n + 1; i++) {
            for (; !st.empty() && arr[st.top().first] >= arr[i]; st.pop()) {
                ans = max(ans, (sum[i - 1] - sum[st.top().second]) * arr[st.top().first]);
            }
            st.emplace(i, st.empty() ? 0 : st.top().first);
        }
        printf("%d\n", ans);
    }
    return 0;
}

今日头条2018校招测试开发方向(第二批)

详情见今日头条2018校园招聘后端开发工程师(第二批)编程题 - 题解

今日头条2018校招测试开发方向(第三批)

详情见今日头条2018校园招聘后端开发工程师(第三批)编程题 - 题解

今日头条2018校招测试开发方向(第四批)

详情见今日头条2018校园招聘后端开发工程师(第四批)编程题 - 题解

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值