9/6 字节笔试第二题单调栈

本文介绍了一道字节跳动笔试题的解题思路,题目要求找出数组中特定函数MAX(i)的最大值,通过使用单调栈算法高效解决。文章详细解释了如何构造单调栈以及如何利用它来寻找数组中符合条件的元素。

9/6 字节笔试第二题单调栈

题目

对于一个有 N 个元素的数组,包含如下的元素 a1,a2, …, an,我们定义了两个函数:
1、L(i) = j 需要满足的条件如下 j < i, a[j] > a[i],如果找不到j的话,L(i) = 0, 有多个 j 选择离 i 最近的
2、R(i) = k 需要满足的条件如下 k > i, a[k] > a[i],如果找不到k的话,L(k) = 0, 有多个 k 选择离 i 最近的

最后我们定义 MAX(i) = L(i) * R(i), 我们需要找到 MAX(i) 的最大值,其中 1 < i < N

输入描述:

总共有两行,第一行是数组长度,第二个是空格分隔的所有数组的内容

输出描述:

输出 MAX(i) 的最大值

示例

输入

5
5 4 3 4 5

输出

8

说明

L(1) = 0, 所以MAX(1) = 0
L(2) = 1, R(2) = 5,  所以MAX(2) = 1 * 5  = 5
L(3) = 2, R(3) = 4,  所以MAX(3) = 2 * 4  = 8
L(4) = 1, R(4) = 5,  所以MAX(2) = 1 * 5  = 5
R(5) = 0,  所以MAX(5) = 0

解题

题目显然是要我们找大于或小于的最近的一个值的位置,可以使用单调栈来处理

import java.util.Scanner;
import java.util.Stack;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] a = new int[n];
        for (int i = 0; i < n; i++){
            a[i] = sc.nextInt();
        }

        //定义变量
        int max = 0;
        int[] l = new int[n];
        Stack<Integer> stack = new Stack<>();

        //求l[i],单调递减栈,后入的比前面的要小
        for (int i = 0; i < n; i++) {
            //找一个 j<i 并且值a[j]>a[i]的,因此小于等于的都要出栈
            while (!stack.isEmpty() && a[stack.peek()] <= a[i]) {
                stack.pop();
            }

            //非空说明找到了,数组下标从0开始,但是结果要从1开始,所以加1
            if (!stack.isEmpty()) {
                l[i] = stack.peek() + 1;
            }

            stack.push(i);
        }

        //清除栈中数据
        while (!stack.isEmpty()) {
            stack.pop();
        }

        //求R[i],单调递减栈,后入的比前面的要小,但是他是从后往前遍历的
        for (int i = n - 1; i >= 0; i--) {
            //找一个 k > i 并且值a[k]>a[i]的,因此小于等于的都要出栈
            while (!stack.isEmpty() && a[stack.peek()] <= a[i]) {
                stack.pop();
            }

            //非空说明找到了,数组下标从0开始,但是结果要从1开始,所以加1
            if (!stack.isEmpty()) {
                max = Math.max(max, l[i] * (stack.peek() + 1));
            }

            stack.push(i);
        }
        System.out.println(max);
    }
}
5
5 4 3 4 5
8
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值