递归算法(求n的加法组合,将一个整数拆分成多个整数相加的形式, O(N)时间,O(N)空间)

原创 2016年08月30日 16:56:20


网上的多种解法比较复杂,本文用递归方法,22行代码搞定。时间和空间复杂度已经降到最低!

第三版:加入创作思路。

这个函数的主要功能就是输出所有组合。既然是输出所有的组合,那就意味着内部有一个遍历所有组合的过程。既然是遍历,而且是O(N)时间,那就说明这个遍历是按照某种输出次序,从“第一个组合”遍历到“最后一个组合”。

如何给组合定义次序呢?举例说明

例1:

3=1+1+1

3=1+2

3=3

上面的例子就说明了次序,即,按照组合中出现数字的从小到大顺序。

定义了次序,剩下的就是如何让程序按照这个程序一个一个的遍历。遍历的过程不会那么完美的一个不重复,当然也会重复,这就涉及到过滤。过滤那些重复的元素,举例说明

例2:

3=1+1+1

3=1+2

3=2+1

3=3

可以看出这个例2中的3=2+1被过滤掉了,并没有输出,这也是必须的,为什么呢?因为3=2+1和之前出现的3=1+2本质上就是一种组合,还要交换一下数字的位置就可以了。而加法自然有交换率。所以就不必输出了。从这里还可以看出来过滤的依据,那就是让一个组合中的所有数字也保持从小到大出现,这样就不会出现3=2+1了,因为2比1大,之前肯定出现过了。这样一来就解决了输出的唯一性

至此,就剩下如递归的进行了。递归的思路是这样的,例如拆分3:

既然

 3=1+后续组合

那么递归也就自然的变成了对“后续组合”进行继续拆分,只要“后续组合“的所有排列找到了,后续组合的每个排列前面加上1这个前缀自然就解决了1作为前缀的所有情况,这样一来就会遍历到

3=1+1+1

3=1+2

由于组合次序的定义可以知道,1作为前缀的情况被遍历完之后,自然就变成了遍历2开头的数字

2开头的数字还需要遍历吗?基于如下事实

n=m1+m2+...+mk, m1<m2<...<mk

第一个数字m1不会超过n/2,因为m1后面的数字要比m1大。所以可以看出,遍历的时候第一个数字最多尝试到n/2.

但是m1最大取n/2是合理的,比如

11=5+6

也就是说拆分的时候总是有拆分成两个数的和的形式,其中n=m1+m2,m1<m2,这样一来m1取n/2就是合适的。

那么下面就是递归程序的实现了。

f(int n,list l,int start)

参数说明:

n:这里n表示要对n进行拆分

l:这里表示子拆分的时候前缀的那些子递增序列,当n被初次拆分的时候,list当然是空的,只有子拆分才会有非空的前缀

start:表示在遍历的时候当前组合的第一个数字,这个数字用来去除重复,参考输出的唯一性

java实现:

public class Sum1ToN {

    private void print(List<Integer> list) {
        for (Integer k : list) {
            System.out.print(k + "+");
        }
    }

    private void f(int n, List<Integer> list, int start) {
        if (n == 1) {
            print(list);
            System.out.println(1);
        } else {
            for (int i = start; i <=n / 2; i++) {
                list.add(i);
                f(n - i, list, i);
                list.remove(list.size() -1);
            }
            print(list);
            System.out.println(n);

        }
    }

    public static void main(String[] args) {
        List<Integer> list = new ArrayList<Integer>();
        new Sum1ToN().f(9,list, 1);
    }

}


 输出:f(9,null,1)

参考:http://blog.csdn.net/calmreason/article/details/8024342

版权声明:欢迎转载,请注明出处:http://blog.csdn.net/bluetjs

如何判断一个整数数组中是否有重复元素?要求时间复杂度O(n),空间复杂度O(1)

题目: 写一个函数判断一个int类型的数组是否是有效的。  所谓有效是指:假设数组大小为n,那么这个int数组里的值为0~n-1之间的数,并且每个数只能出现一次,否则就是无效数组。  例如[...
  • wuli2496
  • wuli2496
  • 2014年12月26日 15:58
  • 1606

现有1,2……一直到n的无序数组,求排序算法,并且要求时间复杂度为O(n),空间复杂度为O(1),使用交换,而且只能交换两个数

 这是今天遇到的一个笔试题,当时想到的思路就是把数值和数组下标关联起来,后来事实证明这个思路是正确的,但是我写的代码出现了一些小偏差,代码如下 //错误代码: #include ...
  • a3789910
  • a3789910
  • 2014年11月22日 19:30
  • 1294

递归算法(求n的加法组合,将一个整数拆分成多个整数相加的形式, O(N)时间,O(N)空间)4.0版

网上的多种解法比较复杂,本文用递归方法,22行代码搞定。时间和空间复杂度已经降到最低!   //n give the sum of a list,and start give the first nu...
  • ClamReason
  • ClamReason
  • 2012年09月27日 11:50
  • 7595

输入一个整形数组,数组里有正数也有负数。数组中连续的一个或多个整数组成一个子数组,每个 子数组都有一个和。求所有子数组的和的最大值。要求时间复杂度为O(n)。

输入一个整形数组,数组里有正数也有负数。数组中连续的一个或多个整数组成一个子数组,每个 子数组都有一个和。求所有子数组的和的最大值。要求时间复杂度为O(n)。 例如输入的数组为1, -2, 3, 10...
  • taotaoah
  • taotaoah
  • 2016年09月08日 14:59
  • 1909

如何判断一个整数数组中是否有重复元素?要求时间复杂度O(n),空间复杂度O(1)

题目: 写一个函数判断一个int类型的数组是否是有效的。  所谓有效是指:假设数组大小为n,那么这个int数组里的值为0~n-1之间的数,并且每个数只能出现一次,否则就是无效数组。  例如[5,...
  • yahohi
  • yahohi
  • 2012年08月23日 17:56
  • 6887

如何判断一个整数数组中是否有重复元素?要求时间复杂度O(n),空间复杂度O(1)

题目: 写一个函数判断一个int类型的数组是否是有效的。  所谓有效是指:假设数组大小为n,那么这个int数组里的值为0~n-1之间的数,并且每个数只能出现一次,否则就是无效数组。  例如[...
  • jazywoo123
  • jazywoo123
  • 2012年09月26日 22:29
  • 1864

如何判断一个整数数组中是否有重复元素?要求时间复杂度O(n),空间复杂度O(1)

题目: 写一个函数判断一个int类型的数组是否是有效的。  所谓有效是指:假设数组大小为n,那么这个int数组里的值为0~n-1之间的数,并且每个数只能出现一次,否则就是无效数组。  例如[...
  • wuli2496
  • wuli2496
  • 2014年12月26日 15:58
  • 1606

给一个正整数N,打印NxN的蛇形矩阵(二) 之空间复杂度O(1)

当N=4时,对应的蛇形矩阵如下图: 图 1 将该蛇形矩阵中元素的坐标代替其元素值时,得到如图2的矩阵,此时横坐标i和纵坐标j的和m=i+j具有一定的规律。当m为偶数时,原矩阵(图1中矩阵)中的...
  • tdmyl
  • tdmyl
  • 2013年10月21日 00:18
  • 3310

给一个正整数N,打印NxN的蛇形矩阵(一) 之空间复杂度O(NxN)

当N=4时,对应的蛇形矩阵如下图: 图 1 将该蛇形矩阵中元素的坐标代替其元素值时,得到如图2的矩阵,此时横坐标i和纵坐标j的和m=i+j具有一定的规律。当m为偶数时,原矩阵(图1中矩阵)中的...
  • ARLoverKang
  • ARLoverKang
  • 2013年10月22日 16:33
  • 644

给一个正整数N,打印NxN的蛇形矩阵(二) 之空间复杂度O(1)

当N=4时,对应的蛇形矩阵如下图: 图 1 将该蛇形矩阵中元素的坐标代替其元素值时,得到如图2的矩阵,此时横坐标i和纵坐标j的和m=i+j具有一定的规律。当m为奇数时,原矩阵(图1中矩阵...
  • ARLoverKang
  • ARLoverKang
  • 2013年10月22日 22:27
  • 791
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:递归算法(求n的加法组合,将一个整数拆分成多个整数相加的形式, O(N)时间,O(N)空间)
举报原因:
原因补充:

(最多只允许输入30个字)