2018今日头条内推笔试2
2017-08-23 13:22
513 查看
对于这道题,假设 区间最小数*区间所有数的和 记为一个区间的K值
我们首先要明确一点:假设有一个区间,它的最小值为a,我们对这个区间进行扩张,当扩张的值大于等于a时,这个区间的K值只增不减,这个很好理解。明白这点之后,我们就不需要遍历序列的所有子区间了,只需要遍历所有扩张之后的区间即可得到最大的K值。
接下来,我们依次以序列中的每个值作为区间的最小值,并且以这个值作为基准,向两边扩张,直到遇到比这个值小的数或者到达序列的一端停止,之后我们计算扩张之后每个区间的K值,得到最大的K值就是题目所要求的。
例如,以图片题中给定的序列[6,2,1]为例,
1.我们以6为基准,左边无法扩张,右边2比6小,无法扩张,所以扩张之后的区间为[6],得到K值为6*6=36;
2.我们以2为基准,左边扩张到6,右边1比2小,无法扩张,所以扩张之后的区间为[6,2],得到K值为2*(2+6)=16
3.我们以1为基准,扩张之后的区间为[6,2,1],K值为1*(1+2+6) = 9
最终得到最大K值为36;
得到解题的思路之后,我们需要考虑的是如何去计算扩张之后区间的K值。这个过程我们使用一种特殊的数据结构:单调栈
我们简单解释一下什么是单调栈:规定栈中元素从栈底到栈顶必须是严格递增的或者严格递减的栈。如果入栈元素不符合栈的单调性,那么我们依次将栈顶元素出栈,直至满足入栈条件或者栈空。对于每一个出栈的元素a,使它出栈的元素就是a右侧离a最近的不大于a的数,a出栈后,栈顶元素就是a左侧离a最近的小于a的数,如果a出栈后栈为空,则表示a左侧没有比a小的数。
根据严格递增的单调栈,每次出栈一个元素,我们就可以找到这个元素两侧离它最近比它小的位置,从而得到以该元素为区间最小值扩张之
4000
后的区间,进而可以求出区间K值。
我们继续用题中的例子:对于数列[6,2,1]我们使用单调递增的栈存储
1.我们把6存进栈中
2.我们想要把2存进栈中,但是违反了栈的单调性,所以先把栈顶元素6出栈,此时,我们计算以6为最小值的扩张区间的K值,由于此时栈为空,所以扩张区间左侧起始位置为0,由于是2导致6出栈,所以扩张区间右侧为0,所以区间从0到0,只有一个元素6,K值为36;
3.计算完以6为最小值的扩张区间之后,我们把2入栈,接下来我们想把1入栈,1<2,违反栈的单调性,同上一步,我们把2出栈,由于此时栈为空,所以扩张区间左侧起始位置为0,由于是1导致2出栈,所以扩张区间右侧为1,所以区间从0到1,K值为16
4.然后,我们把1入栈,由于数列所有元素已经全部入栈,这时候,我们依次把栈中元素出栈,计算K值(方法步骤同上)……
有一点需要注意:由于我们需要的是区间的位置,所以在单调栈中我们存放的是数组元素的下标。
下面结合代码理解一下:
import java.util.*; public class Main{ public static void main(String[] args){ Scanner in = new Scanner(System.in); while(in.hasNext()){ int n = in.nextInt(); int[] a = new int[n+1]; in.nextLine(); for(int i=0;i<n;i++){ a[i] = in.nextInt(); } a = -1; //数组最后加上一个元素-1,使得栈中没出栈的元素全部出栈 int max = 0; Stack<Integer> stack = new Stack<>(); for(int i=0;i<=n;i++){ while(!stack.isEmpty() && a[i]<=a[stack.peek()]){ int temp = a[stack.pop()]; //出栈元素作为扩张区间的最小值 int start = stack.isEmpty() ? -1 : stack.peek(); int sum = 0; for(int j=start+1;j<i;j++){ //计算扩张区间所有元素的和 sum += a[j]; } max = Math.max(max, temp*sum); } stack.push(i); } System.out.println(max); } } }
使用单调栈这种数据结构能够降低时间复杂度,优化算法。
相关文章推荐
- 2018今日头条内推笔试1
- 2018今日头条3.24笔试题目2
- 今日头条2018笔试第二题
- 今日头条2018春季校园招聘研发岗位笔试编程题4
- 今日头条2018校招笔试题之字符串的问题
- 2018春招-今日头条笔试题-第四题(python)
- [置顶] 今日头条2018春季校园招聘研发岗位笔试 题解 临时版
- 今日头条2018春季校园招聘研发岗位笔试编程题第一、二题
- 今日头条2018春招研发岗笔试题目
- 2018春招-今日头条笔试题-第一题(python)
- 2018春招-今日头条笔试题-第三题(python)
- 今日头条2018实习生在线编程笔试题
- 今日头条2018春招笔试题js版本
- 今日头条2018春季校园招聘研发岗位笔试编程题1
- 今日头条2018春季校园招聘研发岗位笔试编程题2
- 2018春招-今日头条笔试题-第二题(python)
- 2018今日头条笔试(第二题)
- [今日头条] 笔试题目2016/9/28
- 今日头条2018校招测试开发方向(第一、二、三、四批)编程题汇总 - 题解
- 括号匹配--今日头条2017年实习生招聘笔试题