1 漢諾塔問題
2 約瑟夫環
3 求“斐波納契數列:1,1,2,3,5,8,13,21..."函數:遞歸與非遞歸
4 判斷一個數是否是 2的冪次數:
5 計算一個整數的二進制數的 1的個數num
6 輸入一個整數數組,調整數組中數字的順序,使得所有奇數位於數組的前半部分,所有偶數位於數組的後半部分。要求時間復雜度為O(n)。 ----像這種要求時間復雜度的 常常需要交換的算法
===========================================================================================
1 漢諾塔問題
//第一,把X上的n-1個盤通過Z移動到Y。
第二,把X上的最下面的盤移到Z。
//第三,因為n-1個盤全在Y上了,所以把Y當做X重復以上步驟就好了。遞歸中會保存數據
void moveNext( char pre, char next ) { cout<<pre<<"-->"<<next<<endl; } void hanio(int n,char XBlock,char YBlock,char ZBlock) { if(n==1) { moveNext(XBlock,ZBlock); } else { hanio(n-1,XBlock,ZBlock,YBlock); moveNext(XBlock,ZBlock); hanio(n-1,YBlock,XBlock,ZBlock); } }
2 約瑟夫環
首先建立一個 首尾相連的循環鏈表,for循環定義計算器,到達m改變鏈表的連接關系。
直到 最後剩下一個結點,pre=purnode。
typedef struct node { int num; struct node *next; }LinkNode;
LinkNode * create_link( int num ) { LinkNode *p,*current,*head; // p用來循環,current用來記錄當前的位置。head(第一個數)用來返回一個鏈表 p=(LinkNode*)malloc(sizeof(LinkNode)); p->num=1; p->next=NULL; head=p; current=p; for(int i=2;i<=num;i++) { //生成新的結點---建立連接----轉移到下一個 p=(LinkNode*)malloc(sizeof(LinkNode)); p->num=i; p->next=NULL; current->next=p; current=p; } current->next=head; //鏈表的rail指向head,構成循環(循環列表list)。 return head; } void make_play( LinkNode *link,int mcode ) { assert(link!=NULL&&mcode!=0); LinkNode *pLink=link,*pPre=NULL; //錯誤:要給pre賦值才能使用。 LinkNode *pDelte; //刪除節點---free標記結點) cout<<"親,游戲開始了!"<<endl; while(pLink!=pPre) //最後只留一個元素。 { for(int n=1;n<mcode;n++) { pPre=pLink; pLink=pLink->next; } pDelte=pLink; cout<<"出列的是"<<pDelte->num<<endl; pPre->next=pLink->next; pLink=pPre->next; free(pDelte); } cout<<"最後出列的是:"<<pLink->num<<endl; }
3 求“斐波納契數列:1,1,2,3,5,8,13,21..."函數:遞歸與非遞歸
主要就是 初始化退出條件)和循環條件轉移遞歸關系)的一個轉換的關系。
int fib( int n ) { /*if(n==1||n==2) { return 1; } else { return fib(n-1)+fib(n-2); }*/ if(n<=2) { return 1; } int valN1,valN2,sumN; //是不是可以寫成static形式的 valN1=1; valN2=1; //sum ,n1,n2往後移動位置 for(int i=1;i<=n-2;i++) //計算的次數 { sumN=valN1+valN2; valN2=valN1; valN1=sumN; } return sumN; }
4 判斷一個數是否是 2的冪次數:0==(a[i]&(a[i]-1)
int find2power( int a[] ,int len) { int count=0; for(int i=0;i<len;i++) { if(0==(a[i]&(a[i]-1))) { count++; } } cout<<count<<endl; return count; }
5 計算一個整數的二進制數的 1的個數num
統計一個整數的二進制數的 1的個數: num&1(一次統計最右邊的那個數值是否是1)
int num1OfBinery( int num ) { int count=0; while(num) { if(num&1) { count++; } num>>=1; //向右移動,除以2 } return count; }
6 輸入一個整數數組,調整數組中數字的順序,使得所有奇數位於數組的前半部分,所有偶數位於數組的後半部分。要求時間復雜度為O(n)。
----像這種要求時間復雜度On)的 常常需要交換的算法:添加一個計算當前遇到的奇數個元素的mark標記標志下一個遇到的奇數應該插入的位置),遇到奇數的話---swapi,mark)
void swapElement( int arr[], int i, int mark ) { int tmp; tmp=arr[i]; arr[i]=arr[mark]; arr[mark]=tmp; } void printArrray( int arr[], int num ) { cout<<"輸出的數組是:"<<endl; for(int i=0;i<num;i++) { cout<<arr[i]<<endl; } } // 兩個變量:一個i遍歷數組,另一個標記需要的位置 有幾個奇數符合條件的,排在前幾位) //1 找到第一個,判斷移動 2 循環 void partition( int arr[],int num ) { int i=0,mark=0; while(i<num&&(arr[i]&1==0)) //找到第一個奇數:= while +if(break) { i++; } if(i==num) //全是偶數 return; swapElement(arr,i,mark); i++; mark++; while(i<num) { if((arr[i]&1)==1) { swapElement(arr,i,mark); mark++; printArrray(arr,num); } i++; } printArrray(arr,num); }
===========================================================================
測試的代碼:
/* int n; printf("請輸入要移動的塊數:"); scanf("%d",&n); hanio(n,'X','Y','Z');*/ int num=7; //cout<<fib(num)<<endl; LinkNode *head=create_link(num); make_play(head,5); int arr[]={1,2,3,4,5,6,7,8,16,50}; int len=sizeof(arr)/sizeof(int); find2power(arr,len); /*int num=7; cout<<num1OfBinery(num)<<endl;*/ /*int arr[]={1,2,4,6,7,5,8,9}; int n=sizeof(arr)/sizeof(int); partition(arr,n);*/