📫 个人主页:深夜coding算法
📣 专栏系列:2026年华为最新OD机试题库详解
🔥 一次订阅,永久解锁 | 持续更新100+篇 | 6语言全覆盖
文章目录
- ❄️前言:
- ☀️一:题目描述
- 🌙 题目名称
- 🌙 题目内容
- 🌙 输入描述
- 🌙 输出描述
- 🌙 示例
- ☀️二:解题思路
- ☀️三:代码实现
- C++
- Java
- Python3
- C语言
- JavaScript
- Go
- ☀️四:复杂度分析
- ⭐ 五:易错点
- 坑1:前缀和数组长度是N+1
- 坑2:差值是绝对值
- 🌻共勉:
❄️前言:
200分题,要求在一个数组中找一个长度K的区间,使得区间和的绝对值与目标值T的差最小。前缀和+滑动窗口,两层优化。前缀和把区间和降到O(1),滑动窗口遍历所有K长度区间。
☀️一:题目描述
🌙 题目名称
计算最接近的数
🌙 题目内容
给定一个长度为 N 的整数数组和一个目标值 T,要求找出一个长度为 K 的连续子数组,使得该子数组的元素之和与 T 的差的绝对值最小。输出这个最小差值。
🌙 输入描述
第一行:N K T(三个整数)
第二行:N 个整数
1 ≤ K ≤ N ≤ 1000
🌙 输出描述
输出最小差值的绝对值。
🌙 示例
输入: 5 2 7 1 2 3 4 5 输出: 0 说明:子数组[3,4]的和为7,与T=7的差为0☀️二:解题思路
前缀和:pre[i] = arr[0]+...+arr[i-1],区间[i, i+K)的和 =pre[i+K] - pre[i]。遍历所有 i,计算差值,取最小。
☀️三:代码实现
C++
#include<iostream>#include<vector>#include<cmath>usingnamespacestd;intmain(){intN,K,T;cin>>N>>K>>T;vector<int>arr(N),pre(N+1,0);for(inti=0;i<N;i++){cin>>arr[i];pre[i+1]=pre[i]+arr[i];}intans=INT_MAX;for(inti=0;i<=N-K;i++){intsum=pre[i+K]-pre[i];ans=min(ans,abs(sum-T));}cout<<ans<<endl;}Java
importjava.util.Scanner;publicclassMain{publicstaticvoidmain(String[]args){Scannersc=newScanner(System.in);intN=sc.nextInt(),K=sc.nextInt(),T=sc.nextInt();int[]pre=newint[N+1];for(inti=0;i<N;i++)pre[i+1]=pre[i]+sc.nextInt();intans=Integer.MAX_VALUE;for(inti=0;i<=N-K;i++){intdiff=Math.abs(pre[i+K]-pre[i]-T);if(diff<ans)ans=diff;}System.out.println(ans);}}Python3
N,K,T=map(int,input().split())arr=list(map(int,input().split()))pre=[0]forxinarr:pre.append(pre[-1]+x)ans=float('inf')foriinrange(N-K+1):diff=abs(pre[i+K]-pre[i]-T)ifdiff<ans:ans=diffprint(ans)C语言
#include<stdio.h>#include<stdlib.h>intmain(){intN,K,T,pre[1024]={0};scanf("%d %d %d",&N,&K,&T);for(inti=0;i<N;i++){intx;scanf("%d",&x);pre[i+1]=pre[i]+x;}intans=0x7fffffff;for(inti=0;i<=N-K;i++){intdiff=abs(pre[i+K]-pre[i]-T);if(diff<ans)ans=diff;}printf("%d\n",ans);}JavaScript
const[nkt,arr]=require('fs').readFileSync(0,'utf-8').trim().split('\n');const[N,K,T]=nkt.split(' ').map(Number);constnums=arr.split(' ').map(Number);constpre=[0];for(constxofnums)pre.push(pre[pre.length-1]+x);letans=Infinity;for(leti=0;i<=N-K;i++)ans=Math.min(ans,Math.abs(pre[i+K]-pre[i]-T));console.log(ans);Go
packagemainimport("fmt";"math")funcmain(){varN,K,Tintfmt.Scan(&N,&K,&T)pre:=make([]int,N+1)fori:=0;i<N;i++{varxint;fmt.Scan(&x)pre[i+1]=pre[i]+x}ans:=math.MaxInt32fori:=0;i<=N-K;i++{diff:=pre[i+K]-pre[i]-Tifdiff<0{diff=-diff}ifdiff<ans{ans=diff}}fmt.Println(ans)}☀️四:复杂度分析
| 指标 | 数值 |
|---|---|
| 时间复杂度 | O(N) |
| 空间复杂度 | O(N) |
⭐ 五:易错点
坑1:前缀和数组长度是N+1
pre[0] = 0表示前 0 个元素的和。
坑2:差值是绝对值
abs(sum - T),不是sum - T。
🌻共勉:
前缀和 + 滑动窗口是OD机试数组题最常用的组合技,熟练掌握能搞定一大半区间类问题。
📫关于本专栏:一次订阅,永久解锁全部100+篇真题详解
🔥6语言全覆盖:Java | Python3 | C++ | C语言 | JsNode | Go