(一)全排列
全排列:从n个不同元素中任取m个元素,按照一定的顺序排列起来,当n=m时,所有的排列情况叫全排列。
f(n)=n!
基本算法:
字典序法,递增进位制数法、递减进位制数发、邻位对换法
递归Recursion(分治法思想)
设(ri)perm(X)表示每一个全排列前加上前缀ri得到的排列.当n=1时,perm(R)=(r) 其中r是唯一的元素,这个就是出口条件.
void Perm(list[],int k,int m) //k表示前缀的位置,m是要排列的数目. { if(k==m-1) //前缀是最后一个位置,此时打印排列数. { for(int i=0;i<m;i++) { printf("%d",list[i]); } printf("n"); } else { for(int i=k;i<m;i++) { //交换前缀,使之产生下一个前缀.如果list[k]=list[i]则不用交换 Swap(list[k],list[i]); Perm(list,k+1,m); //将前缀换回来,继续做下一个的前缀排列. Swap(list[k],list[i]); } } } //此处为引用,交换函数.函数调用多,故定义为内联函数. inline void Swap(int &a,int &b) { int temp=a,a=b,b=temp; }
#include <stdio.h> int n = 0; void swap(int *a, int *b) { int m; m = *a; *a = *b; *b = m; } void perm(int list[], int k, int m) { int i; if(k > m) { for(i = 0; i <= m; i++) printf("%d ", list[i]); printf("\n"); n++; } else { for(i = k; i <= m; i++) { swap(&list[k], &list[i]); perm(list, k + 1, m); swap(&list[k], &list[i]); } } } int main() { int list[] = {1, 2, 3, 4, 5}; perm(list, 0, 4); printf("total:%d\n", n); return 0; }
(二)数值的整数次方【剑指offer-11】
double PowerWithUnsignedExponent (double base,unsigned int exponent) { if (exponent==0)return 1;//递归结束条件 if(exponent==1)return base;//递归结束条件 //递归部分:递归循环量设置 int result = PowerWithUnsignedExponent (base,exponent>>1);//位运算代替除 result*=result; //位运算判断奇偶 if(exponent&0x1=1)result*=base; return result; }
(三)打印1到最大的n位数【剑指offer-12】
提示:n位的整数没有限定n的取值范围,需要考虑大数造成存储溢出问题,字符串是一个简单有效表示大数的方法。
void PrintMaxNbit(int n) { if (n<=0)return; char* number = new char[n]; number[n] ='/0';//初始化 for(int i=0;i<10;i++) { number[0]= i+'0'; PrintMaxNbitRecursion(number,n,0); } delete []number; } void PrintMaxNbitRecursion(char* number,int length,int index) { if(index==length-1)//递归结束条件 { PrintNum(number); return; } for(int i=0;i<10;i++) { number[index]= i+'0'; PrintMaxNbitRecursion(number,length,index+1); } } void PrintNum(char* number) { bool isBeginning = false; int len= strlen(number); for(int i=0;i<len;i++) { if(isBeginning&&number[i]='0')isBeginning=false; if(isBeginning!=0) { cout<<number[i]; } } cout<<endl; }