整数划分问题:将正整数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种。
全排列问题:
递归式如下: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]
*/