找回密码
 立即注册
首页 业界区 安全 剑指offer-41、和为S的连续正数序列

剑指offer-41、和为S的连续正数序列

侧胥咽 2025-11-25 09:30:08
题⽬描述

⼩明很喜欢数学,有⼀天他在做数学作业时,要求计算出 9~16 的和,他⻢上就写出了正确答案是 100 。但是他并不满⾜于此,他在想究竟有多少种连续的正数序列的和为 100 (⾄少包括两个数)。没多久,他就得到另⼀组连续正数和为 100 的序列: 18,19,20,21,22 。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
返回值描述:输出所有和为 S 的连续正数序列。序列内按照从⼩⾄⼤的顺序,序列间按照开始数字从⼩到⼤的顺序
示例1:
输⼊:9
返回值:[[2,3,4],[4,5]]
思路及解答

暴力枚举

通过双重循环尝试所有可能的序列起点和终点。
针对每⼀个索引起点,都计算后续的连续⼦数组的和,并且将元素存到临时 list 中。
如果和不超过 sum ,那么就继续往后⾯遍历;
如果和等于 sum ,则说明该连续⼦数组满⾜条件,将临时 list 添加到结果集中
如果和⼤于 sum ,则说明连续⼦数组已经超过,该索引起点的不满⾜条件,直接 break 。
注意的是,起点我们只需要遍历到 sum/2 的位置即可,因为⼤于 sum/2 的索引,任何两个数的和都⼤于 sum ,不符合条件。
  1. import java.util.ArrayList;
  2. public class Solution {
  3.     public ArrayList> FindContinuousSequence(int sum) {
  4.         ArrayList> result = new ArrayList<>();
  5.         if (sum < 3) return result; // 至少需要两个数,最小和为1+2=3
  6.         
  7.         // 序列起点最多到sum/2,因为至少两个数,第二个数肯定比sum/2大
  8.         for (int i = 1; i <= sum / 2; i++) {
  9.             int currentSum = 0;
  10.             ArrayList<Integer> sequence = new ArrayList<>();
  11.             
  12.             // 从i开始累加,直到和大于等于sum
  13.             for (int j = i; j < sum; j++) {
  14.                 currentSum += j;
  15.                 sequence.add(j);
  16.                
  17.                 if (currentSum == sum) {
  18.                     result.add(new ArrayList<>(sequence)); // 找到有效序列
  19.                     break;
  20.                 } else if (currentSum > sum) {
  21.                     break; // 已经超过,无需继续
  22.                 }
  23.             }
  24.         }
  25.         return result;
  26.     }
  27. }
复制代码


  • 时间复杂度:O(n²)
  • 空间复杂度:O(k),k为结果序列数
数学计算

利用等差数列求和公式进行数学优化,减少计算量。
思路:设序列长度为n,起始为x,则满足:n*(2x+n-1)/2 = sum
  1. import java.util.ArrayList;
  2. public class Solution {
  3.     public ArrayList> FindContinuousSequence(int sum) {
  4.         ArrayList> result = new ArrayList<>();
  5.         if (sum < 3) return result;
  6.         
  7.         // 序列长度n从2开始尝试(至少两个数)
  8.         for (int n = 2; n * (n + 1) / 2 <= sum; n++) {
  9.             // 根据求和公式推导:sum = n*(2x+n-1)/2
  10.             // 解得:x = (2*sum/n - n + 1)/2
  11.             int numerator = 2 * sum - n * (n - 1);
  12.             int denominator = 2 * n;
  13.             
  14.             // x必须是正整数,且分子要能整除分母
  15.             if (numerator > 0 && numerator % denominator == 0) {
  16.                 int x = numerator / denominator;
  17.                 ArrayList<Integer> sequence = new ArrayList<>();
  18.                 for (int i = 0; i < n; i++) {
  19.                     sequence.add(x + i);
  20.                 }
  21.                 result.add(sequence);
  22.             }
  23.         }
  24.         
  25.         // 由于我们从长度小的开始,需要反转结果保证序列间顺序
  26.         result.sort((a, b) -> a.get(0) - b.get(0));
  27.         return result;
  28.     }
  29. }
复制代码


  • 时间复杂度:O(n)
  • 空间复杂度:O(1)
滑动窗口(最优)

使用双指针技术,动态调整窗口大小
[code]import java.util.ArrayList;  public class Solution {      public ArrayList> FindContinuousSequence(int sum) {         ArrayList> result = new ArrayList();         if (sum < 3) return result;                  int left = 1;    // 窗口左边界         int right = 2;   // 窗口右边界         int currentSum = left + right; // 当前窗口和                  // 左边界最多到sum/2,因为至少需要两个数         while (left

相关推荐

2025-11-28 14:28:04

举报

您需要登录后才可以回帖 登录 | 立即注册