😀前言
在牛客网的《剑指 Offer》系列题中,有一道关于输出和为给定值 S 的连续正数序列的问题。这是一道典型的双指针问题,考察我们对连续数列求和的理解和双指针的应用。本文将详细解析这道题的思路,并展示如何实现代码。
🏠个人主页:尘觉主页
文章目录
- 🥰和为 S 的连续正数序列
- 😊题目描述
- 😄题目描述
- 💝解题思路
- 双指针的具体步骤:
- 示例代码
- 代码解析
- 示例运行
- 时间复杂度分析
- 😄总结
🥰和为 S 的连续正数序列
😊题目描述
牛客网
😄题目描述
题目要求:给定一个正整数 SSS,找出所有和为 SSS 的连续正数序列。例如,当 S=100S = 100S=100 时,符合条件的序列有:
[9, 10, 11, 12, 13, 14, 15, 16]
[18, 19, 20, 21, 22]。
💝解题思路
我们需要找到和为 SSS 的连续正数序列,这道题可以使用 双指针 的方法来解决。
双指针的具体步骤:
- 初始化两个指针:设定起始位置
start
为 1,end
为 2,并且计算它们之间的当前和curSum = 3
。 - 滑动窗口调整:
- 如果
curSum
大于 SSS,则需要减小序列和,将start
右移,同时从curSum
中减去start
的值。 - 如果
curSum
小于 SSS,则需要增加序列和,将end
右移,同时将end
的值加到curSum
中。 - 当
curSum
刚好等于 SSS 时,找到了符合条件的序列[start, start + 1, ..., end]
,将该序列存入结果列表中,并继续调整start
和end
寻找下一组符合条件的序列。
- 如果
- 循环终止条件:只要
end < sum
,就继续调整指针,直到遍历完所有可能的序列。
示例代码
以下是完整的 Java 实现代码:
import java.util.ArrayList;
public class ContinuousSequenceSum {
public ArrayList<ArrayList<Integer>> FindContinuousSequence(int sum) {
// 用于存储所有符合条件的连续序列集合
ArrayList<ArrayList<Integer>> result = new ArrayList<>();
// 初始化滑动窗口的左右边界
int start = 1; // 窗口左边界
int end = 2; // 窗口右边界
// 当前窗口的元素和,初始为 start + end
int curSum = start + end;
// 当窗口的右边界未达到 sum 时,继续寻找符合条件的序列
while (end < sum) {
// 如果当前窗口和大于目标值 sum,则需要缩小窗口
if (curSum > sum) {
// 从 curSum 中减去 start,并右移 start 缩小窗口
curSum -= start;
start++;
}
// 如果当前窗口和小于目标值 sum,则需要扩大窗口
else if (curSum < sum) {
// 右移 end,并将新的 end 值加入 curSum 中
end++;
curSum += end;
}
// 当前窗口和正好等于 sum,找到符合条件的序列
else {
// 创建当前序列,并将 start 到 end 的所有整数添加到列表中
ArrayList<Integer> sequence = new ArrayList<>();
for (int i = start; i <= end; i++) {
sequence.add(i);
}
// 将符合条件的序列加入结果集合
result.add(sequence);
// 缩小窗口以寻找下一个可能的序列
curSum -= start;
start++;
end++;
curSum += end;
}
}
// 返回所有符合条件的连续序列集合
return result;
}
public static void main(String[] args) {
ContinuousSequenceSum sequenceFinder = new ContinuousSequenceSum();
int targetSum = 100;
ArrayList<ArrayList<Integer>> sequences = sequenceFinder.FindContinuousSequence(targetSum);
// 输出所有找到的序列
for (ArrayList<Integer> seq : sequences) {
System.out.println(seq);
}
}
}
代码解析
- 变量定义:
ret
用于存储符合条件的序列集合,start
和end
是双指针,用来标记当前连续序列的开始和结束。 - 循环控制:在
while
循环中,start
和end
不断调整,直到curSum
等于 SSS 或者end
达到上限。 - 更新逻辑:每次找到符合条件的序列后,将
curSum
减去start
,然后右移start
指针,以便寻找新的可能序列。
示例运行
以 S = 100
为例,程序将输出:
[9, 10, 11, 12, 13, 14, 15, 16]
[18, 19, 20, 21, 22]
时间复杂度分析
该算法的时间复杂度为 O(n)O(n)O(n),因为 start
和 end
指针在整个过程中最多各自移动 nnn 次。同时,该方法仅使用了常数空间 O(1)O(1)O(1),用于存储结果的空间不计入复杂度。
😄总结
此题使用滑动窗口(双指针)解法,实现简洁高效。掌握这种思路对解决类似连续数列求和问题非常有帮助。
😁热门专栏推荐
想学习vue的可以看看这个
java基础合集
数据库合集
redis合集
nginx合集
linux合集
手写机制
微服务组件
spring_尘觉
springMVC
mybits
等等等还有许多优秀的合集在主页等着大家的光顾感谢大家的支持
🤔欢迎大家加入我的社区 尘觉社区
文章到这里就结束了,如果有什么疑问的地方请指出,诸佬们一起来评论区一起讨论😁
希望能和诸佬们一起努力,今后我们一起观看感谢您的阅读🍻
如果帮助到您不妨3连支持一下,创造不易您们的支持是我的动力🤞