通过率 59% · 提交 471 · 通过 279
小慕有一个由 `n` 个正整数组成的序列,给定一个整数 `sum`,他想找出,使得这个子序列中所有数的和等于 `sum`,并返回这个子序列的长度。如果不存在这样的子序列,则返回 `-1`。
这类题属于华为 OD 机考真题方向中「100分 / 2024E」方向的高频题型,通常考察对「100分 / 2024E」的建模能力与边界条件处理。掌握本题的解题思路后,可举一反三应对同类真题方向,稳步提升机考通过率。
提示:带虚线的词点一下有通俗解释。
第一行为子序列
第二行为给定sum
返回此子序列的长度,如果没有满足条件的序列,返回-1
示例 1
输入示例
1,2,3,4,2 6
输出示例
3
和为6的有1 2 3和2 4,但是1 2 3的长度比2 4的长度长,所以答案为3
示例 2
输入示例
1,2,3,4,2 20
输出示例
-1
没有满足要求的子数组。
时间限制 1000 ms · 内存限制 128 MB
本平台为独立第三方培训机构,与华为技术有限公司无任何关联;课程的服务内容与权益以购买协议为准,学习效果因个人情况而异。「华为 OD」「华为可信」等仅为对岗位与考试方向的客观描述,相关商标归各自权利人所有。
相关图解步骤
先看指定步骤补关键知识点,再回到本题完成标准输入输出。
本题一眼滑窗,直接考虑滑窗三问三答。
right 所指的元素 num,做什么操作?left 右移?left 对应的元素做什么操作?while 中的循环不变量是什么?ans 的更新?num 加入窗口和变量 win_sum 中进行计算。win_sum 的大小超过了目标和 target,减去 left 所指的元素 left_num,同时 left 右移,直到 win_sum 小于等于目标和 target。win_sum 等于目标和 target 时,此时窗口大小为 right - left + 1,更新 ans = max(ans, right - left + 1)。直接在 left 右移之后进行答案更新即可,因为此时 right 对应了以 right 为右边界,且区间和不大于 target 的区间 [left, right]。思路展开 代码里维护三个量:left 是窗口左边界,right 是当前遍历到的右边界,win_sum 是窗口 [left, right] 内所有元素之和。right 每前进一步,先把新元素 num 累加进 win_sum;如果加完后 win_sum 超过了目标值 target,就进入 while 循环,不断把 nums[left] 从和中减掉并把 left 右移,直到窗口和重新不超过 target 为止。这个收缩之所以可行,关键在于题目保证序列全为正整数:窗口每收缩一格,win_sum 严格变小,每扩张一格,win_sum 严格变大,和随边界移动是单调的,所以以 right 结尾、和不超过 target 的最长窗口是唯一确定的,不会漏解。收缩结束后若 win_sum 恰好等于 target,说明当前窗口 [left, right] 就是一个以 right 为右端点、和为 target 的最长连续子序列,用 right - left + 1 更新答案 ans 的最大值。ans 初始化为 -1,若全程没有任何窗口的和恰好等于 target,就按题目要求输出 -1。
复杂度分析 设序列长度为 n。right 遍历全部元素一次,left 只单调右移、累计移动不超过 n 步,每个元素至多进窗一次、出窗一次,因此滑窗整体是 O(n) 时间。除读入的数组本身外,只用了 win_sum、left、ans 三个变量,额外空间复杂度 O(1)。
登录后可查看你在本题的历史提交,以及每次的各用例通过情况。
© 2026 广州慕课网络科技有限公司 · 吴师兄学算法官网 版权所有