c语言数字拆分,在手机上玩C语言—数字拆分

blog_568ae0b70102xd0e.html

看到贴吧有人在人工玩数字拆分,我试试用计算机玩玩数字拆分。玩数字拆分第一个想到的就是用递归方法,具体代码如图1所示,从图1可以看出,代码非常简单。

a4c26d1e5885305701be709a3d33442f.png

图1 拆分数字递归代码

试着对数字6进行拆分,运行递归拆分数字的程序,得结果如图2所示。

a4c26d1e5885305701be709a3d33442f.png

图2 数字6拆分的递归输出

显然,图2中输出数据是不完整的,我们试着把数据重构出来,如图3所示。

a4c26d1e5885305701be709a3d33442f.png

图3-1 数字6拆分完整数据

a4c26d1e5885305701be709a3d33442f.png

图3-2 数字6拆分完整数据

图3中第一行数据是1 5,第二行数据是1 1

4,第二行中第1个1是从上一行中继承下来的,第二行中1和4是从上一行的数字5拆分而来,这就是数据重构的规律,这样我们就在程序中增加一个二维数据,用以记录拆分数据,运行修改后的程序得结果如图4所示。

a4c26d1e5885305701be709a3d33442f.png

图4 数字6的拆分

从图4中可以看出,拆分数据是完整的,拆分也没有遗漏,但有一个问题,拆分数据有大量重复,比如1 1 2 2和1

2 1 2就是重复拆分数据,那接下来要做的改进是去除重复数据,运行修改后的程序,得结果如图5所示。

a4c26d1e5885305701be709a3d33442f.png

图5 数字6拆分的种类

从图5中可以看出,数字6用递归方法拆分出19种,当拆分数字11时,共拆分出557种,如图6所示。

a4c26d1e5885305701be709a3d33442f.png

图6 数字11的拆分种类数

这样问题又来了,我们是用整数类型int定义的二维数组,最大到(貌似)1000*1000,在数字拆分这个问题,这样的数组大小是远不够的,我们改用char类型定义二维数组,此时最大到(貌似)2000*1000,改用char类型数组后,大概最大可以拆分到数字21,我们实际试算了数字19的拆分,如图7所示。

a4c26d1e5885305701be709a3d33442f.png

图7 数字19的拆分

从图7中可以看出,用递归方法拆分数字,数据量巨大,时间复杂度也大,有没有更好的办法,想出了一个迭代公式,f(n)=1*f(n-1)+2*f(n-2)+3*f(n-3)+...+(n-1)*f(1)=Σ(n-i)*f(i),i=1...n-1,这个公式的意义如图8所示。

a4c26d1e5885305701be709a3d33442f.png

图8 数字拆分迭代计算公式

在拆分迭代计算公式中初始值为,1=1,2=2,2=1+1,用代码实现数字拆分迭代公式,试算数字5拆分,其结果如图9所示。

a4c26d1e5885305701be709a3d33442f.png

图9-1 迭代算法v0.1拆分数字5

a4c26d1e5885305701be709a3d33442f.png

图9-2 迭代算法v0.1拆分数字5

从图9中可以看出,用迭代算法拆分数字5结果是正确的,再用迭代算法试算数字6的拆分,如图10所示。

a4c26d1e5885305701be709a3d33442f.png

图10 迭代算法v0.1拆分数字6

从图10可以看出,迭代算法计算数字6的拆分有遗漏,少了一个6=3+3,那我们把迭代算法改进一下,f(n)=Σ(n-i)*f(i)+ceil(n/2)*floor(n/2),这样改进后,数字6拆分是对了,如图11所示。

a4c26d1e5885305701be709a3d33442f.png

图11 迭代算法v0.2拆分数字6

然而,用改进后迭代算法计算数字11的拆分,还是错了,如图12所示。

a4c26d1e5885305701be709a3d33442f.png

图12 迭代算法v0.2计算数字11拆分

从图12可以看出,用改进迭代公式计算拆分有遗漏,以后还作了一点小改进,但用代码实现迭代公式后,运行程序,发现拆分仍有遗漏,此时突然明白,问题不在那上面,而是漏了一个(n-1、1)的拆分,这样将拆分公式改进为f(n)=∑(n-i)*f(i)+(n-1)*1,式中n>=2,i=1...n-1,f(1)=1,

1*(n-1)=1+(n-1)=n,从图12中还可以看出一个问题,那就是拆分出来的种类数很大,而其中绝大部分是重复的,为此,每进行一个数字的拆分都作去重计算,即

迭代拆分算法:

1.迭代计算拆分

2.去重复计算

3.没达到n回到第1步,否则输出拆分数据

用改进后迭代算法,计算数字30的拆分,如图13所示。

a4c26d1e5885305701be709a3d33442f.png

图13 迭代算法v1.0计算数字30的拆分

从图13可以看出,用迭代算法计算数字拆分,时间复杂度和空间复杂度都大为降底,但即使这样,计算一个大一点数字的拆分仍是不可想象的,而递归算法计算数字拆分,如果不考虑去重复问题则受制编译器的递归重数。

一个看似小学生都会的数字拆分,在程序实现上竞有那么多问题,我不知道是否还有更好、更简单算法,也不知道迭代计算数字拆分是我原创,还是早就有了,只是我不知道而己。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值