技术开发 频道

编程小练习:拆分自然数

 【IT168技术文档】

转载自Jeff Zhao的博客   

    今天的题目如下:

 给出sum、min、max和n四个正整数,请输出所有将sum拆分为n个正整数之和,其中每个正整数k都满足:min <= k <= max。这n个正整数之间可以重复,不过由于加法交换率的作用,1 + 2和2 + 1便算是重复的拆分了。

 例如,sum = 5,n = 3,min = 1,max = 3,这时候满足条件的拆分方式只有两种:

 1 + 1 + 3

 1 + 2 + 2

 这个练习和上次不同,我们假设所有的输入都是正整数。您无需对其进行合法性判断,只要专注于业务实现便是。您在看下面的内容之前,不如自己先简单尝试一下?老赵建议,您可以在这里阐述您的思路。至于代码,您可以在自己的博客上写一篇文章,然后再这里贴上链接,如果直接在这里贴代码的话,会使评论列表变得很长,影响阅读。点此展开

 简单枚举

 假设我们最后的结果存放在一个长度为n的int数组中。则解决这道题目最简单的方式,自然为数组的每个元素枚举min到max之间的所有值,并在得到一个枚举序列之后,判断它是否符合题目要求。如果是,则输出。代码如下:

static void PrintDivision(int sum, int n, int min, int max)

 {

 int[] array = new int[n];

 DoSimple(array, 0, min, max);

 }

 private static void DoSimple(int[] array, int n, int minInclusive, int maxInclusive)

 {

 if (n >= array.Length)

 {

 if (IsValidResult(array))

 {

 PrintResult(array);

 }

 return;

 }

 for (int i = minInclusive; i <= maxInclusive; i++)

 {

 array[n] = i;

 DoSimple(array, n + 1, minInclusive, maxInclusive);

 }

 }

  DoSimple的含义为,为array数组下标为n的位置中枚举minInvlusive到maxInclusive之间的所有值,并深入。如果array数组填充完毕,那么判断是否是一个正确的结果,并输出。在这个解法中IsValidResult方法的任务颇为繁重,它除了判断array中所有元素之和是否为sum以外,还要判断这个array所表示的拆分是否已经出现过了。例如在已经输出了1 + 1 + 3的情况下,就不能输出3 + 1 + 1。这些都必须在IsValidResult中进行判断,当然做到这点也并不困难。

 不过这个做法的问题也是很明显的,就是重复太多。如果让我们进行“人力”拆分,我们肯定不会傻呆呆地为每个空格枚举从min到max之间的所有值。我们会知道,如果已经有了1 + 2,那么在出现2的时候,我们就不会再枚举1这个值。那么在编程时,我们又该如何进行限制呢?
原文地址:http://www.cnblogs.com/jeffreyzhao/archive/2009/06/21/1507847.html

0
相关文章