leetcode-连续整数求和

177 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第9天,点击查看活动详情

题目描述

给定一个正整数 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

思路

本题的难度标签是困难,但是耐心分析,做一些基本的公式变换和推理,也没有想象中那么难,可能标签就吓退了不少人吧。
既然是连续的正整数的和,自然而然想到高斯求和公式。我们设这个正整数序列的首项为a,项数为k,那么末项就是(a+k-1),求和公式可以写作n = (a+(a+k-1))*k/2
2边同时乘以2,得到 2n = (a+(a+k-1))*k,由于a和k都是正整数,我们得到第一个筛选条件,k一定是2n的因子。我们整理一下括号里面的内容 2n = (2a+k-1)*k,由于a是正整数,一定满足2a-1 > 0,所以,(2a+k-1) > k,即k是2n的因子,且是比较小的因子。
继续对2n = (a+(a+k-1))*k做变换,得到 2n/k = (2a+k-1),再次变换得到 2n/k - (k-1) = 2a,得到另外一个筛选条件,2n/k - (k-1)一定可以被2整除。 按照上面的思路,令k从1开始,在满足k * k < 2n的范围内遍历,满足筛选条件的就是一组可能的解,求出解的数量即可。

Java版本代码

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