华为OD机试 - 流量波峰 - 数组(Java 双机位C卷 100分)

在这里插入图片描述

华为OD机试 双机位C卷题库疯狂收录中,刷题点这里

专栏导读

本专栏收录于《华为OD机试(JAVA)真题》

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天优快云在线答疑。

一、题目描述

一线运维人员在对通话流量进行监控,每一段时间内都是出现流量的高峰,流量有高有低形成一个个波峰波谷,运维人员想找到流量变化最快的波峰,你可以帮助他吗?

给定一个整数数组nums,代表采样点的流量值,请找到满足以下条件的三元组 (i,j,k): 其中i<j<k,nums[j] > nums[i]且nums[j] > nums[k](即是峰顶),并找到所有满足条件的三元组中(k-i)的最小值

二、输入描述

第一行是一个整数n,表示有几个元素
第一行为n个整数,表示数组中的n个元素,0<= n < =100000

三、输出描述

返回所有满足条件的三元组中(k-i)的最小值。若不存在,返回-1。

四、测试用例

测试用例1:

1、输入

6
3 5 4 7 2 1

2、输出

2

3、说明

满足条件的三元组为[0, 1, 2],距离2

测试用例2:

1、输入

4
4 3 2 1

2、输出

-1

3、说明

无法找到满足条件的三元组,返回-1

五、解题思路

目标是最小化 k-i,且存在峰顶 j:i<j<k、nums[j] > nums[i] 且 nums[j] > nums[k]。

对固定峰顶 j,k-i = (j-i)+(k-j),左右两侧距离互不影响,因此应选离 j 最近的左侧严格更小元素与离 j 最近的右侧严格更小元素。

使用单调递增栈分别求每个位置的“最近左侧严格更小”和“最近右侧严格更小”,时间 O(n),空间 O(n),适合 n≤100000。

六、Java算法源码

public class OdTest {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = Integer.valueOf(sc.nextLine());

        if (n < 3) {
            System.out.print(-1);
            return;
        }

        String[] arr = sc.nextLine().split(" ");

        int[] nums = new int[n];
        for (int i = 0; i < arr.length; i++) {
            nums[i] = Integer.parseInt(arr[i]);
        }

        int[] leftLess = new int[n];  // 每个位置左侧最近严格更小的索引
        int[] rightLess = new int[n]; // 每个位置右侧最近严格更小的索引
        Arrays.fill(leftLess, -1);
        Arrays.fill(rightLess, -1);

        // 单调递增栈:栈中索引对应的值严格递增
        int[] stack = new int[n];
        int top = -1;

        // 求左侧最近严格更小
        for (int i = 0; i < n; i++) {
            // 弹出所有 >= 当前值的索引,保证栈顶严格更小
            while (top >= 0 && nums[stack[top]] >= nums[i]) {
                top--;
            }
            leftLess[i] = (top >= 0) ? stack[top] : -1;
            stack[++top] = i;
        }

        // 求右侧最近严格更小(从右向左)
        top = -1;
        for (int i = n - 1; i >= 0; i--) {
            while (top >= 0 && nums[stack[top]] >= nums[i]) {
                top--;
            }
            rightLess[i] = (top >= 0) ? stack[top] : -1;
            stack[++top] = i;
        }

        int ans = Integer.MAX_VALUE;
        for (int j = 0; j < n; j++) {
            if (leftLess[j] != -1 && rightLess[j] != -1) {
                ans = Math.min(ans, rightLess[j] - leftLess[j]);
            }
        }

        System.out.print(ans == Integer.MAX_VALUE ? -1 : ans);
    }
}

七、效果展示

1、输入

5
5 1 4 3 2

2、输出

2

3、说明

峰顶 4 的最近左小是 1,最近右小是 3,距离 2。

在这里插入图片描述


🏆下一篇:华为OD机试 - 简易内存池 - 逻辑分析(Java 双机位C卷 200分)

🏆本专栏收录于《华为OD机试(JAVA)真题》

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天优快云在线答疑。

在这里插入图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哪 吒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值