递归之整数划分问题和排列问题

 整数划分问题:将正整数n表示成一系列正整数之和;将最大加数n1不大于m的划分个数记作q(n,m)
 递归式如下:q(n,m) = 1     n=1,m=1
 = q(n,n) n<m
 = 1+q(n,n-1) n=m
   = q(n,m-1)+q(n-m,m)   n>m>1
 
 举例:
 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;
 q(6,4)==9即在6的所有整数划分中,最大加数不大于4(<=4)的划分有9种。

看实现的代码:

import java.util.*;
public class IntHuaFen {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		int m = in.nextInt();
		System.out.println(q(n,m));
	}
	
	static int q(int n,int m){
		if((n<1)||(m<1)) return 0;
		if((n==1)||(m==1)) return 1;
		if(n<m) return q(n,n);
		if(n==m) return q(n,m-1)+1;
		return q(n,m-1)+q(n-m,m);
	}
}
/*
6 4
9
 */

全排列问题:

设R={r1,r2....rn}是要排列的n个元素,记Ri=R-{ri},集合X的全排列记为perm(X).

其递归定义为:

当n=1时,perm(R)={r};

当n>1时,perm(R)={{(r1)perm(R1)},{(r2)perm(R2)},......{(rn)perm(Rn)}}即递归的求解,固定一个数放到第一位并求剩下的全排列,依次递归

程序中有个地方比较难理解,举个列子,并附上自己的解释(不一定严谨):

以list[3]={1,2,3}为例,
一、先1与1自己对换,把1放到第一位置,递归排列23
(1)对于23,先2与2自己对换,把2放到第一位(注意放到的是本次需排列数字即23的第一位)递归排列3
a、然后3与3对换,把3放到第一位,发现只有一个元素,打印数组中的所有元素{123},回归到(1)
(2)先2与3对换,把3放到第一位,注意所排数字仍然是23,递归排列2
b、2与2对换,把2放到第一位,发现只有一个元素,打印数组中的所有元素{132},回归到(2)
(3)排列23完成,对换3与2,还原为123,返回到一
二、把1与2对换,把2放到第一位置,递归排列13
。。。。省略,同一相同,直到所有排列结束。

看代码:

public class QuanPaiLie {

	public static void main(String[] args) {
		int []arr = new int[]{3,2,5,6};
		perm(arr,1,3);//只排列后三个数

	}
	public static void perm(int list[],int k,int m){
		//产生list[k:m]的所有排列
		if(k==m){
			//只有一个元素
			/*for(int i=0;i<=m;i++)
				System.out.print(list[i]);*/
			System.out.println(Arrays.toString(list));
		} 		
		else //多个元素
			for(int i=k;i<=m;i++){
				swap(list,k,i);//可理解为从第一个元素开始依次的取数放到所排范围的第一个
				perm(list,k+1,m);
				swap(list,k,i);//可理解为每排完一组,都要复原,一遍在原序列基础上取下一个数放到第一位置
			}					//再开展第二组的排序
	}
	
	public static void swap(int arr[],int a,int b){
		int temp = arr[a];
		arr[a] = arr[b];
		arr[b] = temp;
	}
}
/*
[3, 2, 5, 6]
[3, 2, 6, 5]
[3, 5, 2, 6]
[3, 5, 6, 2]
[3, 6, 5, 2]
[3, 6, 2, 5]
 */


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值