1.全排列算法
题目:求出1-n的全排列.
思想:交换第1个元素与第i个元素,得到n个序列;把每个序列分成两部分:第一个元素,其余的元素;对其余元素执行全排列操作,记得操作完后,将这两个元素交换回来,以方便下面的交换.
算法实现:
void Swap(int a, int b) // 交换a和b
{
int temp = a;
a = b;
b = temp;
}
void Perm(int list[], int k, int m) //生成list [k:m ]的所有排列方式
{
int i;
if (k == m)
{
for (i = 0; i <= m; i++)
putchar(list[i]);
putchar('\n');
}
else //递归
for (i=k; i <= m; i++) {
Swap (list[k], list[i]);
Perm (list, k+1, m);
Swap (list [k], list [i]);
}
}
注:此算法没有考虑重复性
2.整数划分
题目:将正整数n表示成一系列整数之和,在正整数n的所有不同划分中,将最大加数n1不大于m的划分个数记做split(n,m).
思想:
(1)当n = 1或m = 1时,split的值为1,可根据上例看出,只有一个划分1 或 1 + 1 + 1 + 1 + 1 + 1,可用程序表示为if(n == 1 || m == 1) return 1;
(2) m > n
在整数划分中实际上最大加数不能大于n,因此在这种情况可以等价为split(n, n);
(3) m = n
这种情况可用递归表示为split(n, m - 1) + 1,从以上例子中可以看出,就是最大加数为6和小于6的划分之和
(4) m < n
这是最一般的情况,在划分的大多数时都是这种情况。
从上例可以看出,设m = 4,那split(6, 4)的值是最大加数小于4划分数和整数2的划分数的和。因此,split(n, m)可表示为split(n, m - 1) + split(n - m, m).
算法实现:
int split(int n, int m)
{
if(n < 1 || m < 1) return 0;
if(n == 1 || m == 1) return 1;
if(n < m) return split(n, n);
if(n == m) return (split(n, m - 1) + 1);
if(n > m) return (split(n, m - 1) + split((n - m), m));
}