• 2018今日头条笔试(第二题)


    题目描述

    给定一个数组序列,需要选出一个区间,使得该区间是所有区间中经过如下计算的值最大的一个。

    区间中的最小数 * 区间所有数的和

    最后程序输出经过计算后的最大值即可,不需要输出具体的区间。如给定序列[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

    则程序输出36

    区间所有数字都在【0,100】的范围内。

    解题思路:

    可以看出我们需要维护一个区间,同时我们能知道区间的最小值,和这个区间所有数字的和。

    但是,有一点我们可以清楚知道,如果一个区间的最小值已经确定,那么我们就要尽量使得区间的和最大。其实本问题就可以转换到遍历数组,以当前位置为最小值,向左向右>=当前值能扩展的最大距离问题,我们知道这样的方法时间复杂度是O(n^2)。

    嗯 区间的最小值和区间边界我们可以用单调栈去维护,这样时间复杂度就降到O(n)

    其实大小都有了,输出区间边界也就不难了。我这里 输出了最大值和 区间的开始结束位置。如果有多个区间=max,我输出的是字典序较小的区间,代码如下:

    给几个比较有用的数据

    1

    0

    ans: 

    0

    1 1

    ---------------------

    9

    1 1 1 1 1 1 1 2 2

    ans:

    11

    1 9

    ----------------

    4

    1 3 2 4

    ans:

    18

    2 4

    ----------------

    #include <iostream>
    #include <stdio.h>
    #include <vector>
    using namespace std;
    typedef long long ll;
    ll a[100010];
    class node {
        public:
            ll left, right,x;
    };
    ll sum[100010];
    int main() {
        // 维护一个递增的栈
        int n;
        vector<node> st;
        while (cin>>n) {
            ll ans = -1;
            if (n == 0) {
                cout << 0 << endl << 0 << " " << 0 << endl;continue;
            }
            ll l = 0,  r = 0;
            while (!st.empty()) st.pop_back();
            sum[0] = 0;
            for (int i = 1; i <= n; ++i) {
                scanf("%lld",&a[i]);
                sum[i] = sum[i-1] + a[i];
            }
            for (int i = 1; i <= n; ++i) {
                if (st.empty()) {
                    st.push_back({i,i,a[i]});
                } else {
                    node u = st.back();
                    if (a[i] > u.x) {
                        st.push_back({i,i,a[i]});
                    } else {
                        int ileft=0,iright=0;
                        while (!st.empty()) {
                            node v = st.back();
                            if (v.x >= a[i]) {
                                st.pop_back();
                                ileft = v.left;
                                if(st.size()) st.back().right = v.right;
                                ll tmp = (sum[v.right] - sum[v.left-1])*v.x;
                                if (tmp >= ans) {
                                    ans = tmp;
                                    l = v.left;
                                    r = v.right;
                                }
                            } else break;
                        }
                        st.push_back({ileft,i,a[i]});
                    }
                }
            }
            while (!st.empty()) {
                node v = st.back();
                st.pop_back();
                if(st.size()) st.back().right = v.right;
                ll tmp = (sum[v.right] - sum[v.left-1])*v.x;
                if (tmp >= ans){
                    ans = tmp;
                    l = v.left;
                    r = v.right;
                }
            }
            cout << ans << endl << l << " " << r << endl;
        }
        return 0;
    }
  • 相关阅读:
    图解集合5:不正确地使用HashMap引发死循环及元素丢失
    图解集合4:HashMap
    图解集合3:CopyOnWriteArrayList
    图解集合2:LinkedList
    SharePoint PowerShell 修改母版页
    SharePoint PowerShell 启动工作流
    SharePoint REST 服务获取讨论版问题
    SharePoint 前端开发常用的对象之_spPageContextInfo
    SharePoint 读取内容的插件之SharepointPlus
    SharePoint 配置PowerShell任务计划
  • 原文地址:https://www.cnblogs.com/pk28/p/7417558.html
Copyright © 2020-2023  润新知