整数划分算法原理与实现

本文为原创,如需转载,请注明作者和出处,谢谢!

    整数划分问题是将一个正整数n拆成一组数连加并等于n的形式,且这组数中的最大加数不大于n。
    如6的整数划分为
   
    6
    5 + 1
    4 + 2, 4 + 1 + 1
    3 + 3, 3 + 2 + 1, 3 + 1 + 1 + 1
    2 + 2 + 2, 2 + 2 + 1 + 1, 2 + 1 + 1 + 1 + 1
    1 + 1 + 1 + 1 + 1 + 1
   
    共11种。下面介绍一种通过递归方法得到一个正整数的划分数。
   
    递归函数的声明为 int split(int n, int m);其中n为要划分的正整数,m是划分中的最大加数(当m > n时,最大加数为n),
    1 当n = 1或m = 1时,split的值为1,可根据上例看出,只有一个划分1 或 1 + 1 + 1 + 1 + 1 + 1
    可用程序表示为if(n == 1 || m == 1) return 1;
   
    2 下面看一看m 和 n的关系。它们有三种关系
    (1) m > n
    在整数划分中实际上最大加数不能大于n,因此在这种情况可以等价为split(n, n);
    可用程序表示为if(m > n) return split(n, n);   
    (2) m = n
    这种情况可用递归表示为split(n, m - 1) + 1,从以上例子中可以看出,就是最大加
    数为6和小于6的划分之和
    用程序表示为if(m == n) return (split(n, m - 1) + 1);
    (3) m < n
    这是最一般的情况,在划分的大多数时都是这种情况。
    从上例可以看出,设m = 4,那split(6, 4)的值是最大加数小于4划分数和整数2的划分数的和。
    因此,split(n, m)可表示为split(n, m - 1) + split(n - m, m)
   
    根据以上描述,可得源程序如下:
  

#include <stdio.h>

   int split(int n, int m)
   {
      if(n < 1 || m < 1) return 0;
      if(n == 1 || m == 1) return 1;
      if(n < m) return split(n, n);
      if(n == m) return (split(n, m - 1) + 1);
      if(n > m) return (split(n, m - 1) + split((n - m), m));
  }

int main()
{
     printf("12的划分数: %d", split(12, 12));
    return 0;
}

将正整数划分成连续的正整数之和

如15可以划分成4种连续整数相加的形式:

15

7 8

4 5 6

1 2 3 4 5

    首先考虑一般的形式,设n为被划分的正整数,x为划分后最小的整数,如果n有一种划分,那么

结果就是x,如果有两种划分,就是x和x x + 1, 如果有m种划分,就是 x 、x x + 1 、 x x + 1 x + 2 、... 、x x + 1 x + 2 ... x + m - 1

将每一个结果相加得到一个公式(i * x + i * (i - 1) / 2) = n,i为当前划分后相加的正整数个数。

满足条件的划分就是使x为正整数的所有情况。

如上例,当i = 1时,即划分成一个正整数时,x = 15, 当i = 2时, x = 7。

当x = 3时,x = 4, 当x = 4时,4/9,不是正整数,因此,15不可能划分成4个正整数相加。

当x = 5时,x = 1。

    这里还有一个问题,这个i的最大值是多少?不过有一点可以肯定,它一定比n小。我们可以做一个假设,

假设n可以拆成最小值为1的划分,如上例中的1 2 3 4 5。这是n的最大数目的划分。如果不满足这个假设,

那么 i 一定比这个划分中的正整数个数小。因此可以得到这样一个公式i * (i + 1) / 2 <= n,即当i满足

这个公式时n才可能被划分。

综合上述,源程序如下

int split1(int n)
{
    int i, j, m = 0, x, t1, t2;
   // 在这里i + 1之所以变为i - 1,是因为i * (i - 1) / 2这个式子在下面多次用到,
  // 为了避免重复计算,因此将这个值计算完后保存在t1中。并且将<= 号变为了<号。
    for(i = 1; (t1 = i * (i - 1) / 2) < n; i++) 
    {
        t2 = (n - t1);
        x =  t2 / i;
        if(x <= 0) break;
        if((n - t1) % i == 0)
        {
            printf("%d ", x);
            for(j = 1; j < i; j++)
                printf("%d ", x + j);
            printf("/n");
            m++;
        }
    }
    return m;
}

国内最棒的Google Android技术社区(eoeandroid),欢迎访问!

《银河系列原创教程》发布

时间: 2025-01-27 03:16:17

整数划分算法原理与实现的相关文章

银河系列原创教程

本文为原创,如需转载,请注明作者和出处,谢谢!     本文为银河系列原创技术文章,主要包括Struts 2入门系列教程.Struts1.x入门与提高系列教程.WebService大讲堂之Axis2系列教程.Weblogic10+EJB3入门教程.AJAX系列教程.SQL Server2005杂谈系列教程.算法系列教程.这些文章均为笔者经验总结,有的系列文章还未完成,待不断完善中... Struts 2入门系列教程  1.  第一个Struts2程序  2.  处理一个form多个submit

深入理解C指针之一:初识指针

原文:深入理解C指针之一:初识指针 简单来说,指针包含的就是内存地址.理解指针关键在于理解C的内存管理模式.C里面有三种内存: ①.静态全局内存(生命周期从程序开始到程序结束,全局变量作用域是全局,静态变量作用域在定义它们的函数内部): ②.自动内存(在函数内部声明的变量,在函数被调用时创建,作用域和生命周期都在函数内部): ③.动态内存(内存分配在堆上,根据需要释放,通过指针引用,作用域局限于引用的指针): 下面先来声明一个指针并打印其地址和值,这里p%指的是以十六进制的形式返回数据: #in

计算机网络原理相关面试问题

1.简单介绍OSI的七层网络模型,画图描绘,描述主要几层的各自作用.OSI(Open System Interconnect,开放系统互连)七层网络模型. TCP/IP四层模型和OSI七层模型 表1-1是 TCP/IP四层模型和OSI七层模型对应表.我们把OSI七层网络模型和Linux TCP/IP四层概念模型对应,然后将各种网络协议归类. 表1-1  TCP/IP四层模型和OSI七层模型对应表 OSI七层网络模型 Linux TCP/IP四层概念模型 对应网络协议 应用层(Applicatio

详析手机端的8PX原理

  淘宝网的官方Blog有篇「一张图解释手机端8px原理」,简单来说就是把 iOS 和 Android 放在一起比较.同时探讨 1x.2x.ldpi.mdpi.hdpi.Xhdpi.xxhdpi 的尺寸与分辨率.本文就以我个人角度提出看法.(图片取自 Android – Devices and Displays) 8px 的文章内容就我的理解是基于「iOS 接口和 Android 接口长得完全一样」的情况下进行开发所写.iOS 和 Android 是两种完全不同的系统,用户操作习惯完全不同,在开

网页设计技巧案例:借助数学原理构建视觉效果

文章描述:让这些数学理论来为你网页设计撑腰. 古老的数学原理已经存在了成百上千年,但是依然能够帮助我们提高设计水平,你相信吗?这些数学原理经得起时间的检验,能够在构图上给予我们指导,帮助我们构建更加和谐的视觉效果. 你可能在设计中曾经用到过数学原理,也可能没有.无论如何,数学规律适用于各种设计,从印刷设计再到网页设计.因此理解这些数学的原理,就能让你的设计更加的好看.更高瞻远瞩. 黄金比例 黄金比例,也可以说是黄金矩形或者黄金分割,最理想的比例是1.618.这种原理的起源上不知晓,但是黄金比例无

PHP底层的运行机制与原理

PHP入门很简单,但是要精通也不是一件简单的事.我们除了会使用之外,还得知道它底层的工作原理.   PHP是一种适用于web开发的动态语言.具体点说,就是一个用C语言实现包含大量组件的软件框架.更狭义点看,可以把它认为是一个强大的UI框架.   了解PHP底层实现的目的是什么?动态语言要像用好首先得了解它,内存管理.框架模型值得我们借鉴,通过扩展开发实现更多更强大的功能,优化我们程序的性能.  1. PHP的设计理念及特点 多进程模型:由于PHP是多进程模型,不同请求间互不干涉,这样保证了一个请

理解php原理的opcodes(操作码)

Opcondes是一种php脚本编译后的中间语言,就像Java的Byte Code,或者.NET 的MSL .(都没了解过~) 举个文中的例子 复制代码 代码如下: <?php echo "Hello World"; $a = 1 + 1; echo $a; ?> PHP执行这段代码会经过如下4个步骤(确切的来说,应该是PHP的语言引擎Zend) 复制代码 代码如下: 1.Scanning(Lexing) (扫描),将PHP代码转换为语言片段(Tokens) 2.Parsi

Thrift的TProtocol类体系原理及源码详解:紧凑协议类TCompactProtocolT(TCom

Thrift的TProtocol类体系原理及源码详解:紧凑协议类TCompactProtocolT(TCompactProtocol) 这个协议类采用了zigzag 编码,这种编码是基于Variable-length quantity编码提出来 的,因为Variable-length quantity编码对于负数的编码都需要很长的字节数,而zigzag 编 码对于绝对值小的数字,无论正负都可以采用较少的字节来表示,充分利用了 Varint技术. 所以这个协议类采用zigzag 编码可以节省传输空

浅析Linux中的时间编程和实现原理(一) Linux应用层的时间编程

引子 我们都生活在时间中,但却无法去思考它.什么是时间呢?似乎这是一个永远也不能被回答的问题.然而作为一个程序员,在工作中,总有那么几次我必须思考什么是时间.比如,需要知道一段代码运行了多久:要在 log 文件中记录事件发生时的时间戳:再比如需要一个定时器以便能够定期做某些计算机操作.我发现,在计算机世界中,时间在不同场合也往往有不同的含义,让试图思考它的人感到迷茫.但值得庆幸的是,Linux 中的时间终究是可以理解的.因此我打算讨论一下有关时间的话题,尝试着深入理解 Linux 系统中 C 语