☰
华为OD机试真题 新系统 2026-10-28 JavaGoC【AI推理任务并行额度】
2026/11/1 1:56:17 网站建设 项目流程

目录

题目

思路

Code

题目

题目内容:

有 n 个 AI 推理任务按顺序排队,第 i 个任务需占用 vram[i] GB 显存;调度器可选定一个任务 i 为基准,向左右连续合并相邻任务(即连续子数组),合并条件是被合并任务的显存占用不低于 vram[i]。

已知任务的并行执行额度值 = vram[i] × 任务个数(满足条件的连续子数组长度);对于给定的任务序列 vram,请计算该序列中可达到的并行额度最大值是多少。

输入描述:

本题为核心代码模式,你需要实现函数 maxTaskVram(vram)。

参数 vram 为整数数组,长度为 n,1 ≤ n ≤ 10^5,0 ≤ vram[i] ≤ 10^4。

输出描述:

返回任务的并行执行额度最大值。

样例1

输入:

vram = [2,1,5,6,2,3]

输出:

10

思路

整体思路:

固定某个显存值为基准时,应尽量扩展左右范围,直到遇到更小的显存值。问题等价于寻找连续区间的最小值乘区间长度的最大结果,可用单调栈一次扫描完成。

第一步:

用栈保存还未确定右边界的任务下标,并保持栈中显存从底到顶不递减。新任务显存更高或相等时,之前的任务仍可以向右扩展。

第二步:

当新任务显存低于栈顶时,栈顶任务不能继续跨过当前任务扩展,因此当前下标就是它的右侧阻挡位置。弹出该任务,计算它作为基准的额度。

第三步:

弹出后,新栈顶下标记为 left;栈为空时令 left = −1。可计入的区间是 left+1 到当前下标 i−1,宽度为 i−left−1,用弹出任务的显存乘宽度更新最大值。

第四步:

弹出的任务可能与左侧任务显存相同,此时先计算较短区间,左侧同高任务之后仍会计算完整区间,不会漏掉最优解。处理完所有应弹出的任务后,把当前任务下标压栈。

第五步:

扫描到数组末尾时,使用一个虚拟显存 −1 作为哨兵。真实显存均非负,它会清空栈并补算所有尚未遇到右侧阻挡位置的任务,不修改原数组。

边界处理:

零显存基准产生额度 0;相等显存能够共同扩展;单任务、单调递增和单调递减都由同一流程处理。最大额度为 10^4 × 10^5 = 10^9。

复杂度分析:

每个任务下标最多入栈和出栈一次,时间复杂度 O(n),额外空间 O(n)。

Code

import java.io.BufferedInputStream; import java.io.IOException; public class Main { public static int maxTaskVram(int[] vram) { int n = vram.length; // 栈内存储任务下标;size 是有效元素数,显存值从栈底到栈顶不递减。 int[] stack = new int[n]; int size = 0; int best = 0; for (int i = 0; i <= n; i++) { // -1 是虚拟尾任务,严格小于真实非负显存,确保剩余任务全部结算。 int current = i < n ? vram[i] : -1; // 遇到更低显存,栈顶基准不能跨过当前任务,i 成为右侧阻挡位置。 while (size > 0 && vram[stack[size - 1]] > current) { int height = vram[stack[--size]]; // 空栈允许从 0 开始;若左侧显存相同,后续由更左任务计算完整宽度。 int left = size > 0 ? stack[size - 1] : -1; int width = i - left - 1; // 可选任务为 left+1 到 i-1;最大乘积 10^9,不会超出 int 范围。 best = Math.max(best, height * width); } // 尾部仅清栈,避免把虚拟下标 n 写进容量为 n 的数组。 if (i < n) { stack[size++] = i; } } return best; } private static int nextInt(BufferedInputStream input) throws IOException { int c; // 本地大规模输入只含非负整数,跳过空白后按十进制读,减少逐词扫描开销。 do { c = input.read(); } while (c != -1 && c <= ' '); if (c == -1) { return -1; } int value = 0; // 遇到分隔空白停止;该分隔符被读走,下一次调用继续寻找下一个整数。 while (c >= '0' && c <= '9') { value = value * 10 + c - '0'; c = input.read(); } return value; } public static void main(String[] args) throws IOException { BufferedInputStream input = new BufferedInputStream(System.in); int n = nextInt(input); if (n == -1) { return; } int[] vram = new int[n]; // 长度只用于本地适配,提交时直接给 maxTaskVram 传入显存数组。 for (int i = 0; i < n; i++) { vram[i] = nextInt(input); } System.out.println(maxTaskVram(vram)); } }

Go

package main import ( "bufio" "fmt" "os" ) func maxTaskVram(vram []int) int { n := len(vram) // 栈保存未确定右边界的任务下标,栈底到栈顶对应显存不递减。 stack := make([]int, 0, n) best := 0 for i := 0; i <= n; i++ { // 默认为虚拟尾值 -1;真实任务覆盖它,尾部则清空所有剩余候选。 current := -1 if i < n { current = vram[i] } // 当前任务显存更小,栈顶基准的区间必须在 i 前结束。 for len(stack) > 0 && vram[stack[len(stack)-1]] > current { height := vram[stack[len(stack)-1]] stack = stack[:len(stack)-1] // 无左边界时允许从 0 扩展,同高的左任务会在后续结算更宽区间。 left := -1 if len(stack) > 0 { left = stack[len(stack)-1] } width := i - left - 1 value := height * width // 两个边界都不计入宽度,用显存乘任务数更新最大并行额度。 if value > best { best = value } } // 哨兵只负责触发出栈,不作为实际任务入栈。 if i < n { stack = append(stack, i) } } return best } func main() { input := bufio.NewReader(os.Stdin) var n int if _, err := fmt.Fscan(input, &n); err != nil { return } vram := make([]int, n) // 输入长度属于本地适配协议,核心函数只使用显存切片。 for i := range vram { fmt.Fscan(input, &vram[i]) } fmt.Println(maxTaskVram(vram)) }

C

#include <stdio.h> #include <stdlib.h> int maxTaskVram(const int vram[], int n) { // 数组长度需独立传入;每个任务最多入栈一次,n 个下标槽位足够。 int *stack = malloc((size_t)n * sizeof(int)); // size 表示有效栈长,栈内任务显存保持不递减。 int size = 0; int best = 0; for (int i = 0; i <= n; i++) { // 尾部虚拟值 -1 低于所有真实显存,会结算包括零值在内的剩余任务。 int current = i < n ? vram[i] : -1; // 更小显存阻断栈顶任务的右扩展,当前下标 i 不计入它的区间。 while (size > 0 && vram[stack[size - 1]] > current) { int height = vram[stack[--size]]; // 左边为空时从 0 开始;左侧同高任务尚未弹出,稍后计算更宽区间。 int left = size > 0 ? stack[size - 1] : -1; int width = i - left - 1; int value = height * width; // 每个已确定区间都与当前最优比较,最大 10^9 在本地 32 位 int 范围内。 if (value > best) { best = value; } } // 不把哨兵下标 n 写入栈,避免越过分配的 n 个元素。 if (i < n) { stack[size++] = i; } } // 栈只属于函数内部,结算完后释放;调用方的显存数组不被修改或释放。 free(stack); return best; } int main(void) { int n; if (scanf("%d", &n) != 1) { return 0; } int *vram = malloc((size_t)n * sizeof(int)); // 本地协议读取 n 个显存值,最后由适配器释放它拥有的输入数组。 for (int i = 0; i < n; i++) { scanf("%d", &vram[i]); } printf("%d\n", maxTaskVram(vram, n)); free(vram); return 0; }

【华为od机试真题Python+JS+Java+Go合集】【超值优惠】:Py/JS/Java/Go合集

【华为od机试真题Python】:Python真题题库

【华为od机试真题JavaScript】:JavaScript真题题库

【华为od机试真题Java&Go】:Java&Go真题题库

【华为od机试真题C++】:C++真题题库

【华为od机试真题C语言】:C语言真题题库

【华为od面试手撕代码题库】:面试手撕代码题库

【华为od机试面试交流群】【文章底部有二维码链接,可扫码加交流群】

华为OD机试:二本院校有机会吗? 有机会,但不大,大神除外!机考分数越高越好,所以需要提前刷题。机考通过后,如果没有收到面试邀请,也不要着急,非目标院校面试邀请发的时间比较晚。非目标院校今年有点难,机试至少要考到350分,所以需要疯狂刷题,华为OD机考是有题库的,最好在考前完所有题库题目。华为OD机试:跨专业可以参加华为OD可以,但是如果你的本科院校比较差,上岸概率不大。华为OD机试:华为OD简历被锁定机试通过,性格测试也通过,但是没人联系面试,发现简历被锁定。此时需要主动去联系HR。让他帮助你查询原因。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询