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

在这里插入图片描述

华为OD机试双机位C卷统一考试题库清单(持续收录中)以及考点说明(Python/JS/C/C++)

专栏导读

本专栏收录于《华为OD机试真题(Python/JS/C/C++)》

刷的越多,抽中的概率越大,私信哪吒,备注华为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。

六、Python算法源码

import sys

def main():
    data = sys.stdin.read().strip().split()
    if not data:
        print(-1)
        return
    nums = list(map(int, data))
    n = len(nums)
    if n < 3:
        print(-1)
        return

    left_less = [-1] * n
    right_less = [-1] * n

    # 单调递增栈,栈中索引对应值严格递增
    stack = []
    for i in range(n):
        while stack and nums[stack[-1]] >= nums[i]:
            stack.pop()
        left_less[i] = stack[-1] if stack else -1
        stack.append(i)

    stack = []
    for i in range(n - 1, -1, -1):
        while stack and nums[stack[-1]] >= nums[i]:
            stack.pop()
        right_less[i] = stack[-1] if stack else -1
        stack.append(i)

    ans = None
    for j in range(n):
        if left_less[j] != -1 and right_less[j] != -1:
            dist = right_less[j] - left_less[j]
            ans = dist if ans is None else min(ans, dist)

    print(-1 if ans is None else ans)

if __name__ == "__main__":
    main()

七、JavaScript算法源码

const fs = require('fs');

const input = fs.readFileSync(0, 'utf8').trim();
if (input.length === 0) {
  console.log(-1);
  process.exit(0);
}
const nums = input.split(/\s+/).map(Number);
const n = nums.length;
if (n < 3) {
  console.log(-1);
  process.exit(0);
}

const leftLess = new Array(n).fill(-1);
const rightLess = new Array(n).fill(-1);

// 单调递增栈,保存索引
let stack = [];
for (let i = 0; i < n; i++) {
  while (stack.length && nums[stack[stack.length - 1]] >= nums[i]) {
    stack.pop();
  }
  leftLess[i] = stack.length ? stack[stack.length - 1] : -1;
  stack.push(i);
}

stack = [];
for (let i = n - 1; i >= 0; i--) {
  while (stack.length && nums[stack[stack.length - 1]] >= nums[i]) {
    stack.pop();
  }
  rightLess[i] = stack.length ? stack[stack.length - 1] : -1;
  stack.push(i);
}

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

console.log(ans === Infinity ? -1 : ans);

八、C算法源码

#include <stdio.h>
#include <stdlib.h>

int main() {
    int capacity = 1024;
    int *nums = (int *)malloc(sizeof(int) * capacity);
    int n = 0;

    // 读取所有整数
    while (1) {
        int x;
        if (scanf("%d", &x) != 1) break;
        if (n >= capacity) {
            capacity *= 2;
            nums = (int *)realloc(nums, sizeof(int) * capacity);
        }
        nums[n++] = x;
    }

    if (n < 3) {
        printf("-1");
        free(nums);
        return 0;
    }

    int *leftLess = (int *)malloc(sizeof(int) * n);
    int *rightLess = (int *)malloc(sizeof(int) * n);
    int *stack = (int *)malloc(sizeof(int) * n);
    int top = -1;

    for (int i = 0; i < n; i++) leftLess[i] = -1;
    for (int i = 0; i < n; i++) rightLess[i] = -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 = 2147483647;
    for (int j = 0; j < n; j++) {
        if (leftLess[j] != -1 && rightLess[j] != -1) {
            int dist = rightLess[j] - leftLess[j];
            if (dist < ans) ans = dist;
        }
    }

    if (ans == 2147483647) printf("-1");
    else printf("%d", ans);

    free(nums);
    free(leftLess);
    free(rightLess);
    free(stack);
    return 0;
}

九、C++算法源码

#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    vector<int> nums;
    int x;
    // 读取所有整数
    while (cin >> x) nums.push_back(x);

    int n = nums.size();
    if (n < 3) {
        cout << -1;
        return 0;
    }

    vector<int> leftLess(n, -1), rightLess(n, -1);
    vector<int> stack;

    // 左侧最近严格更小
    for (int i = 0; i < n; i++) {
        while (!stack.empty() && nums[stack.back()] >= nums[i]) {
            stack.pop_back();
        }
        leftLess[i] = stack.empty() ? -1 : stack.back();
        stack.push_back(i);
    }

    // 右侧最近严格更小
    stack.clear();
    for (int i = n - 1; i >= 0; i--) {
        while (!stack.empty {
        while (!stack.empty() && nums[stack.back()] >= nums[i]) {
            stack.pop_back();
        }
        rightLess[i] = stack.empty() ? -1 : stack.back();
        stack.push_back(i);
    }

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

    cout << (ans == INT_MAX ? -1 : ans);
    return 0;
}


🏆下一篇:华为OD机试真题 - 简易内存池(Python/JS/C/C++ 双机位C卷 200分)

🏆本文收录于,华为OD机试真题(Python/JS/C/C++)

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

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

哪 吒

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

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

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

打赏作者

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

抵扣说明:

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

余额充值