Leetcode.829 连续整数求和

文章介绍了LeetCode第829题的解题思路,涉及寻找连续正整数之和等于给定值n的所有组合。通过分析等差数列的性质,得出求解公式并给出C++和Java的代码实现,主要利用了平方根下界和偶数特性来优化搜索过程。
摘要由CSDN通过智能技术生成

题目链接

Leetcode.829 连续整数求和 Rating : 1694

题目描述

给定一个正整数 n,返回 连续正整数满足所有数字之和为 n的组数 。

示例 1:

输入: n = 5
输出: 2
解释: 5 = 2 + 3,共有两组连续整数([5],[2,3])求和后为 5。

示例 2:

输入: n = 9
输出: 3
解释: 9 = 4 + 5 = 2 + 3 + 4

示例 3:

输入: n = 15
输出: 4
解释: 15 = 8 + 7 = 4 + 5 + 6 = 1 + 2 + 3 + 4 + 5

提示:
  • 1 < = n < = 1 0 9 ​​​​​​​ 1 <= n <= 10^9​​​​​​​ 1<=n<=109​​​​​​​

分析:等差数列

按照题意,我们要求的 n其实是一段 d = 1的等差数列的和。

等差数列 a n a_n an 的通项为 a n = a 1 + ( n − 1 ) ∗ d a_n = a_1 + (n-1)*d an=a1+(n1)d

等差数列的求和公式为 s = ( a 1 + a n ) ∗ n 2 s = \frac{(a_1+a_n)*n}{2} s=2(a1+an)n

我们假设选取连续的一段 k个元素是满足要求的,即 ( a 1 + a k ) ∗ k 2 = n \frac{(a_1+a_k)*k}{2} = n 2(a1+ak)k=n,这里的 a 1 a_1 a1只是我们假设的第一项。

证明:

先化简为 2 a 1 + ( k − 1 ) ∗ d = 2 n k 2a_1 + (k-1) * d = \frac{2n}{k} 2a1+(k1)d=k2n

因为 d = 1,所以 2 a 1 + k − 1 = 2 n k 2a_1 + k-1 = \frac{2n}{k} 2a1+k1=k2n,在整理一下 2 n k − k + 1 = 2 a 1 \frac{2n}{k} - k + 1 = 2a_1 k2nk+1=2a1

因为我们是从 1n中开始选的,所以 a 1 ≥ 1 a_1\geq1 a11,即 2 n k − k + 1 ≥ 2 \frac{2n}{k} - k + 1 \geq 2 k2nk+12 2 n k ≥ k + 1 \frac{2n}{k} \geq k + 1 k2nk+1

所以 2 n k > k \frac{2n}{k} > k k2n>k k < 2 n k < \sqrt{2n} k<2n ,最后求出了 k k k 的最大值。

因为 2 a 1 + k − 1 = 2 n k 2a_1 + k-1 = \frac{2n}{k} 2a1+k1=k2n 2 a 1 + k − 1 2a_1 + k-1 2a1+k1肯定是一个正整数,所以 2 n 2n 2n 就是 k k k的倍数

又因为 2 n k − k + 1 = 2 a 1 \frac{2n}{k} - k + 1 = 2a_1 k2nk+1=2a1 2 a 1 2a_1 2a1是一个偶数,所以 2 n k − k + 1 \frac{2n}{k} - k + 1 k2nk+1 就是 2的倍数

所以我们最终只需要从 1 1 1 遍历到 2 n \sqrt{2n} 2n ,满足这两个条件的就是一个答案。

时间复杂度: O ( n ) O(\sqrt{n}) O(n )

C++代码:


class Solution {
public:
    int consecutiveNumbersSum(int n) {
        int ans = 0;
        for(int k = 1;k * k <= 2 * n;k++){
            if((2*n) % k == 0 && ((2*n)/k - k + 1) % 2 == 0) ans++; 
        }
        return ans;
    }
};

Java代码:


class Solution {
    public int consecutiveNumbersSum(int n) {
        int ans = 0;
        for(int k = 1;k * k <= 2 * n;k++){
            if((2*n) % k == 0 && ((2*n)/k - k + 1) % 2 == 0) ans++; 
        }
        return ans;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值