今日头条编程第二题的两种解法

动态规划

枚举以i开始序列长度为l的最小值算序列积

F[i][l] 以i开始的长度为l的最小值

//最小值

F[i][l] = min{F[i][l-1],A[i+l-1]}

result = max{F[i][l] *(sum[i+l-1]-sum[i-1]) | 1≤i≤n}

      public static void Main()
        {
            string line;
            string[] p;
            int n = 0;
            while((line = Console.ReadLine())!=null){
                p = line.Split(' ');
                n = Convert.ToInt32(p[0]);
                int[] sum = new int[n+1];
                int[] A = new int[n + 1];
                int[,] v_min = new int[n + 1, n + 1];
                sum[0] = 0;
                p = Console.ReadLine().Split(' ');
                for(int i=1;i <= n;i++){
                    A[i] = Convert.ToInt32(p[i - 1]);
                    sum[i] = sum[i - 1] + A[i];
                }
                int max = -1;
                for(int i=1;i<=n;i++){
                    for(int l=1;l <= n - i + 1;l++){
                        if(l == 1){
                            v_min[i, l] = A[i];
                        }
                        else{
                            if(A[ l + i - 1] < v_min[i,l-1] ){
                                v_min[i, l] = A[l + i - 1];
                            }
                            else{
                                v_min[i, l] = v_min[i, l - 1];
                            }
                        }
                        max = Math.Max(max ,v_min[i, l] * (sum[i + l - 1] - sum[i - 1]));
                    }
                }
                Console.WriteLine(max);
            }
        }
/*
* 把每个数字看成最小值,由于区间是[0,200]所以符合条件的区间越大值越高
* 找到这个数的左边界和右边界
* 最后把每个数字的序列积算出来取最大值
* r[i]:A[i]右边第一个小于A[i]的下标
* l[i]:A[I]左边一个小于A[I]的下标
* F(i) = max{ A[k] * (sum(r[k]) - sum(l[k]-1)) | k∈[1,i]}
*/
public static void Main()
        {
            string line;
            string[] p;
            int n = 0;
            while ((line = Console.ReadLine()) != null){
                p = line.Split(' ');
                n = Convert.ToInt32(p[0]);
                int[] sum = new int[n + 1];
                int[] A = new int[n + 1];
                int[] left = new int[n+1];
                int[] right = new int[n + 1];
 
                sum[0] = 0;
                p = Console.ReadLine().Split(' ');
                for (int i = 1; i <= n; i++){
                    A[i] = Convert.ToInt32(p[i - 1]);
                    sum[i] = sum[i - 1] + A[i];
                }
                for (int i = 1; i <= n;i++ ){  //找右边的边界
                    int j = i;
                    right[i] = n;
                    while(j<=n){
                        if (A[j] < A[i]){
                            right[i] = j-1;
                            break;
                        }
                        j++;
                    }
                }
                for (int i = n; i >= 1;i-- ){ //找左边的边界
                    int j = i;
                    left[i] = 1;
                    while(j>=1){
                        if (A[j] < A[i]){
                            left[i] = j + 1;
                            break;
                        }
                        j--;
                    }//while
                }//for
                int ans = -1;
                for (int i = 1; i <= n;i++ ){
                    ans = Math.Max(ans,A[i] *( sum[right[i]] - sum[left[i]-1]));
                }
                Console.WriteLine(ans);
            }
        }



#字节跳动#
全部评论
我写个我的想法吧,我认为是分治, 首先考虑数组的最小值,哪些区间可以取到取小值,取到最小值,使得结果最大,当然是和最大,那就是全部的数,接下来这个最小值就可以不考虑了,分别对左半和右半重复上面处理。
点赞 回复 分享
发布于 2017-08-23 21:33
复杂度O(500000^2)。能过吗?
点赞 回复 分享
发布于 2017-08-23 21:28
第二个方法赞,有点类似于leetcode上的Largest Rectangular in histogram,有那么点类似的题型。昨天一直在优化暴力方法,a了0.5 
点赞 回复 分享
发布于 2017-08-23 09:28
我是这么做的,提示内存不够
点赞 回复 分享
发布于 2017-08-23 09:22
请问这两种方法都可以ac吗?楼主笔试的时候测试过吗?感觉会超时呀?
点赞 回复 分享
发布于 2017-08-23 08:41
点赞 回复 分享
发布于 2017-08-23 07:04

相关推荐

03-27 16:40
已编辑
门头沟学院 C++
26学院本太难了,很多公司机筛就给我刷了。机会都难拿到如果是简历存在问题也欢迎拷打————————————————————分割线——————————————————————2026.3.4更新:发完贴之后,时不时投递又收到了不少的笔试/面试邀请。主要是之前投递简历出去之后基本上都是沉默状态,年后好转了不少timeline:2026.01.21&nbsp;文远知行笔试,半年多没刷算法题&nbsp;-&gt;挂&nbsp;(后续HR说春招可以重新安排笔试)2026.2.4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;小鹏汇天&nbsp;技术一面,第二周收到结果&nbsp;-&gt;挂2026.2.12&nbsp;&nbsp;&nbsp;大众Cariad代招&nbsp;技术二面&nbsp;-&gt;Offer2026.2.28&nbsp;&nbsp;&nbsp;多益网络技术面试,由于风评太差,一直在犹豫要不要接面试&nbsp;-&gt;推迟-----------分割线-----------2026.3&nbsp;月前的某一天,临时去电网报名了二批计算机岗位的笔试2026.3.6&nbsp;从上家公司实习离职,氛围最好的一家公司,leader&nbsp;说可以帮忙转正,但是流程太长,而且我们部门据说只有一个&nbsp;hc,更想要研究生,我很有可能是会被签外包公司在这里干活,就离职了。2026.3.9&nbsp;入职新公司,大众Cariad&nbsp;以外部公司的身份进组,项目组签了三年,后续三年应该都可以在这里呆,不知道有没有希望原地跳槽。2026.3.10&nbsp;电网考试居然说我通过资格审查了,短信约我去参加资格审查,请假一天,买了&nbsp;12&nbsp;号晚上的机票回成都2026.3.15&nbsp;参加国家电网计算机类笔试2026.3.17&nbsp;电网出成绩了,感觉很低。觉得已经🈚️了2026.3.18&nbsp;收到电网面试通知,通知&nbsp;3.22-3.25&nbsp;这个时间去面试,我的岗位只招&nbsp;1&nbsp;个人。据说面试只有&nbsp;2-3&nbsp;人,不知道能不能成功----------分割线-----------2026.3.21&nbsp;电网面试结束,感觉回答的还勉勉强强,大概是2个岗位分别招1个人,一共11人面试,实际来了9人2026.3.27&nbsp;出面试成绩,满分100分,早上10:20左右发现面试成绩46,我震惊了,没截图,后面过了十分钟重新看发现面试成绩给我改成58了。但同样震惊。朋友问我是不是把面试官打了,哈哈
点赞 评论 收藏
分享
在考古的丘比特很冷艳:[牛泪我横向一周多自动挂了,面试答的还行,感觉挂的莫名其妙
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务