8.9华为OD机试真题 新系统 - 查找最佳充电策略 (Java/Py/C/C++/Js/Go)
查找最佳充电策略
2026 华为OD机试真题8月9日华为OD上机新系统考试真题 100 分题型
点击查看华为 OD 机试真题完整目录:2026最新华为OD机试新系统卷 + 双机位C卷 真题题库目录|全覆盖题库 + 逐点算法考点详解
题目描述
给定一个一维数组priceArray,表示未来priceRecords小时内每小时的电价(单位:分/kWh)。
找出充电成本最低的连续hours个小时时间段的开始时刻点。
若存在多种成本最低方案,优先返回最低成本方案的最早的时刻点。
输入描述
- 参数 1:整数
priceRecords,表示电价记录数量 - 参数 2:整数
hours,表示连续小时数 - 参数 3:一维数组
priceArray,表示每小时的电价price1~priceN - 约束条件:
1 <= priceRecords <= 24,1 <= hours <= priceRecords,1 <= price[i] <= 100
输入为三行:
priceRecords hours priceArray其中priceArray按示例使用英文逗号分隔,允许逗号后有空格。
输出描述
返回一个整数,表示最优充电时段的起始索引(从 0 开始)。
示例1
输入
12 3 25,15,20,18,12,25,30,28,22,16,14,35输出
2说明
连续 3 小时的最低电价时段是索引 2-4,价格分别为 20,18,12,总费用为 50 分。
示例2
输入
12 4 23,35,67,68,89,12,24,37,57,10,12,45输出
7说明
连续 4 小时的最低电价时段是索引 7-10,价格分别为 37,57,10,12,总费用为 116 分。
解题思路
核心思想
需要在长度为priceRecords的数组中找到长度恰好为hours的连续子数组,使子数组和最小。使用固定长度滑动窗口即可在线性时间内完成。
算法步骤
- 从左到右遍历电价数组,把当前价格加入窗口和。
- 当窗口长度超过
hours时,移除窗口左端价格。 - 当窗口长度等于
hours时,用当前窗口和更新最小成本。 - 只有当当前窗口和严格小于历史最小值时才更新答案,因此相同成本会保留更早起点。
复杂度分析
设电价记录数量为n。
- 时间复杂度:
O(n),每个元素最多进出窗口一次。 - 空间复杂度:
O(1),只使用常数个变量。
Java
importjava.util.*;publicclassMain{staticintsolve(intpriceRecords,inthours,int[]prices){// 固定长度滑动窗口,窗口和表示当前连续 hours 小时的总费用intleft=0;intsum=0;intbestIndex=0;intbestCost=Integer.MAX_VALUE;for(intright=0;right<priceRecords;right++){sum+=prices[right];while(right-left+1>hours){sum-=prices[left++];}if(right-left+1==hours&&sum<bestCost){bestCost=sum;bestIndex=left;}}returnbestIndex;}publicstaticvoidmain(String[]args){Scannerscanner=newScanner(System.in);intpriceRecords=Integer.parseInt(scanner.nextLine().trim());inthours=Integer.parseInt(scanner.nextLine().trim());String[]parts=scanner.nextLine().trim().split(",");int[]prices=newint[parts.length];for(inti=0;i<parts.length;i++){prices[i]=Integer.parseInt(parts[i].trim());}System.out.println(solve(priceRecords,hours,prices));}}Python
defsolve(price_records,hours,prices):# 维护长度为 hours 的窗口总费用,只在发现更低费用时更新起点left=0total=0best_index=0best_cost=float("inf")forrightinrange(price_records):total+=prices[right]whileright-left+1>hours:total-=prices[left]left+=1ifright-left+1==hoursandtotal<best_cost:best_cost=total best_index=leftreturnbest_index price_records=int(input().strip())hours=int(input().strip())prices=[int(x.strip())forxininput().strip().split(",")]print(solve(price_records,hours,prices))JavaScript
constreadline=require("readline");functionsolve(priceRecords,hours,prices){// 固定长度滑动窗口,窗口和越小代表充电成本越低letleft=0;lettotal=0;letbestIndex=0;letbestCost=Infinity;for(letright=0;right<priceRecords;right++){total+=prices[right];while(right-left+1>hours){total-=prices[left++];}if(right-left+1===hours&&total<bestCost){bestCost=total;bestIndex=left;}}returnbestIndex;}constrl=readline.createInterface({input:process.stdin,output:process.stdout});constlines=[];rl.on("line",line=>lines.push(line));rl.on("close",()=>{constpriceRecords=Number(lines[0].trim());consthours=Number(lines[1].trim());constprices=lines[2].trim().split(",").map(x=>Number(x.trim()));console.log(solve(priceRecords,hours,prices));});C++
#include<bits/stdc++.h>usingnamespacestd;intsolve(intpriceRecords,inthours,constvector<int>&prices){// 枚举所有长度为 hours 的连续窗口,记录最小窗口和的最早起点intleft=0;intsum=0;intbestIndex=0;intbestCost=INT_MAX;for(intright=0;right<priceRecords;right++){sum+=prices[right];while(right-left+1>hours){sum-=prices[left++];}if(right-left+1==hours&&sum<bestCost){bestCost=sum;bestIndex=left;}}returnbestIndex;}intmain(){intpriceRecords,hours;string line;cin>>priceRecords>>hours;cin.ignore(numeric_limits<streamsize>::max(),'\n');getline(cin,line);vector<int>prices;stringstreamss(line);string item;while(getline(ss,item,',')){prices.push_back(stoi(item));}cout<<solve(priceRecords,hours,prices)<<endl;return0;}Go
packagemainimport("bufio""fmt""os""strconv""strings")funcsolve(priceRecordsint,hoursint,prices[]int)int{// 固定窗口长度为 hours,向右滑动时同步维护窗口和left:=0total:=0bestIndex:=0bestCost:=int(^uint(0)>>1)forright:=0;right<priceRecords;right++{total+=prices[right]forright-left+1>hours{total-=prices[left]left++}ifright-left+1==hours&&total<bestCost{bestCost=total bestIndex=left}}returnbestIndex}funcmain(){reader:=bufio.NewReader(os.Stdin)line1,_:=reader.ReadString('\n')line2,_:=reader.ReadString('\n')line3,_:=reader.ReadString('\n')priceRecords,_:=strconv.Atoi(strings.TrimSpace(line1))hours,_:=strconv.Atoi(strings.TrimSpace(line2))parts:=strings.Split(strings.TrimSpace(line3),",")prices:=make([]int,0,len(parts))for_,part:=rangeparts{value,_:=strconv.Atoi(strings.TrimSpace(part))prices=append(prices,value)}fmt.Println(solve(priceRecords,hours,prices))}C语言
#include<stdio.h>#include<stdlib.h>#include<string.h>#include<limits.h>intsolve(intpriceRecords,inthours,intprices[]){// 使用固定长度滑动窗口,严格更小时才更新,保证并列时返回最早起点intleft=0;inttotal=0;intbestIndex=0;intbestCost=INT_MAX;for(intright=0;right<priceRecords;right++){total+=prices[right];while(right-left+1>hours){total-=prices[left++];}if(right-left+1==hours&&total<bestCost){bestCost=total;bestIndex=left;}}returnbestIndex;}intmain(){intpriceRecords,hours;charline[1024];scanf("%d",&priceRecords);scanf("%d",&hours);getchar();fgets(line,sizeof(line),stdin);line[strcspn(line,"\r\n")]='\0';intprices[32];intcount=0;char*token=strtok(line,",");while(token!=NULL){prices[count++]=atoi(token);token=strtok(NULL,",");}printf("%d\n",solve(priceRecords,hours,prices));return0;}完整用例
用例1
12 3 25,15,20,18,12,25,30,28,22,16,14,35用例2
12 4 23,35,67,68,89,12,24,37,57,10,12,45用例3
5 1 5,4,3,2,1用例4
5 5 10,20,30,40,50用例5
6 2 5,5,9,1,1,8用例6
8 3 9,8,7,1,2,3,4,5用例7
10 4 10,10,10,10,1,1,1,1,50,60用例8
4 2 100,1,100,1用例9
24 6 30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7用例10
7 3 4,3,2,1,2,3,4文章目录
- **查找最佳充电策略**
- 题目描述
- 输入描述
- 输出描述
- 示例1
- 示例2
- 解题思路
- 核心思想
- 算法步骤
- 复杂度分析
- Java
- Python
- JavaScript
- C++
- Go
- C语言
- 完整用例
- 用例1
- 用例2
- 用例3
- 用例4
- 用例5
- 用例6
- 用例7
- 用例8
- 用例9
- 用例10
