一个自然数拆分成连续自然数的和

1. 能否拆分

    结论:除了 $2^n$ 之外,其他自然数均可以拆分

    所有奇数都能写成 $2i + 1$ 的形式,因此至少可以拆成 $(i, i+1)$,所以奇数可以拆分

    偶数里边,奇数倍数的可以拆分,其他的(也就是 $2^n$) 无法拆分

 1 boolean ifConsistOfConsecutiveInteger(int n) {
 2     if (n <= 0) {
 3         return false;
 4     }
 5     boolean result = false;
 6     if ((n & (n - 1)) != 0) {
 7         result = true;
 8     }
 9 
10     return result;
11 }

2. 输出可以拆分成的各种形式

    2.1 数学方法

          以 $a$ 表示连续自然数中的第一个,则

          $n = a + (a + 1) + (a + 2) + ... + (a + k - 1)$

          整理一下

          $2n = 2ka + k^2 - k$

          整理成关于 $k$ 的一元二次方程

     $k^2 + (2a - 1)k - 2n = 0$

     解这个方程,$Delta = (2a -1)^2 + 8n$

   $k = (1 - 2a + sqrt{Delta})/2$

      然后,考虑三个问题

      1) 连续自然数序列里的第一个数必然小于等于 $n/2$,如果大于的话,再和后面的数相加肯定大于 $n$

      2) $Delta$ 开方之后必须是整数

      3) $1 - 2a + sqrt{Delta}$ 必须是偶数,否则除以 $2$ 会出现小数

    代码如下($n$ 太大时不适用,会有溢出):

 1 void printExpression(int n) {
 2     long first;
 3     long incr;
 4     for (int i = 1; i <= n / 2; i++) {
 5         first = i;
 6         long delta = (2 * first - 1) * (2 * first - 1) + 8 * n;
 7         long sqrt_delta = (int) Math.sqrt(delta);
 8 
 9         if (sqrt_delta * sqrt_delta == delta && sqrt_delta % 2 != 0) {
10             incr = (sqrt_delta - (2 * first - 1)) / 2;
11             System.out.println("num of consecutive integer is " + incr);
12             for (int j = 1; j <= incr; j++) {
13                 System.out.print(first + j - 1 + " ");
14             }
15             System.out.println();
16         }
17     }
18 }

     2.2 双指针解法(参考剑指 Offer)

 1 void printExpression2(int n) {
 2     int small = 1;
 3     int big = 2;
 4     int sum = small + big;
 5     while (small <= n / 2) {
 6         if (sum == n) {
 7             for (int i = small; i <= big; i++) {
 8                 System.out.print(i + " ");
 9             }
10             System.out.println();
11         }
12         while (sum > n) {
13             sum -= small;
14             small++;
15 
16             if (sum == n) {
17                 for (int i = small; i <= big; i++) {
18                     System.out.print(i + " ");
19                 }
20                 System.out.println();
21             }
22         }
23 
24         big++;
25         sum += big;
26     }
27 }
原文地址:https://www.cnblogs.com/ainsliaea/p/11221186.html