八、求循环节
八、求循環(huán)節(jié)
文章目錄
- 八、求循環(huán)節(jié)
- 題目描述
- 解題思路
- 上機(jī)代碼
題目描述
對于任意的真分?jǐn)?shù) N/M ( 0 < N < M ),均可以求出對應(yīng)的小數(shù)。如果采用鏈表存儲各位小數(shù),對于循環(huán)節(jié)采用循環(huán)鏈表表示,則所有分?jǐn)?shù)均可以表示為如下鏈表形式。
輸入: N M
輸出: 整個(gè)循環(huán)節(jié)
要求: 編寫一個(gè)盡可能高效的查找循環(huán)節(jié)起始點(diǎn)的函數(shù): NODE * find( NODE * head, int * n ) 。函數(shù)的返回值為循環(huán)節(jié)的起點(diǎn)(即圖中的指針p),n為循環(huán)節(jié)的長度。
說明:提交程序時(shí)請同時(shí)提交將分?jǐn)?shù)轉(zhuǎn)換為小數(shù)的函數(shù) change( int n, int m, NODE * head ) (前面題目中已經(jīng)編寫)。
將分?jǐn)?shù)轉(zhuǎn)換為小數(shù)的函數(shù) change()我們在 六、求循環(huán)小數(shù) 中已經(jīng)編寫過了,可以直接拷貝過來
預(yù)設(shè)代碼:
/* PRESET CODE BEGIN - NEVER TOUCH CODE BELOW */#include <stdio.h> #include <stdlib.h> typedef struct node { int data;struct node * next; } NODE;NODE * find( NODE * , int * ); void outputring( NODE * ); void change( int , int , NODE * ); void outputring( NODE * pring ) { NODE * p;p = pring;if ( p == NULL )printf("NULL");elsedo { printf("%d", p->data);p = p->next;} while ( p != pring );printf("\n");return; }int main() { int n, m;NODE * head, * pring;scanf("%d%d", &n, &m);head = (NODE *)malloc( sizeof(NODE) );head->next = NULL;head->data = -1;change( n, m, head );pring = find( head, &n );printf("ring=%d\n", n);outputring( pring );return 0; }/* Here is waiting for you. void change( int n, int m, NODE * head ) { }NODE * find( NODE * head, int * n ) {} *//* PRESET CODE END - NEVER TOUCH CODE ABOVE */| 測試用例 1 | 1 3 | ring=1 3 | 1秒 | 64M | 0 |
| 測試用例 2 | 1 8 | ring=0 NULL | 1秒 | 64M | 0 |
| 測試用例 3 | 29 33 | ring=2 87 | 1秒 | 64M | 0 |
| 測試用例 4 | 2 7 | ring=6 285714 | 1秒 | 64M | 0 |
解題思路
change()函數(shù)我們已經(jīng)編寫過了,直接拷貝過來即可,這里就只考慮find()函數(shù)的編寫
我們借助于編寫change()時(shí)的思想,將 p1、p2 設(shè)置為全局變量。這樣,判斷如果 p2 > p1 ,即可證明存在循環(huán)
存在循環(huán),循環(huán)的長度即為 p2 - p1 的距離,否則長度為0。
仔細(xì)觀察outputring()函數(shù)發(fā)現(xiàn),函數(shù)從循環(huán)節(jié)開始的位置出發(fā),將循環(huán)節(jié)打印一圈后終止。所以我們在find()函數(shù)中越過 p1 長度的前綴,直接將循環(huán)節(jié)開始的位置返回即可。
上機(jī)代碼
#include <string.h> int p1 = 0, p2 = 0; void change(int n, int m, NODE *head ) {//初始化int shang[10010], yushu[10010];memset(shang, 0, sizeof(shang));memset(yushu, 0, sizeof(yushu));p1 = 0, p2 = 0;int flag = 0;int num = n * 10;for (int i = 0; ; i++){shang[i] = num / m;yushu[i] = num % m;for (int j = 0; j < i; j++){/* 當(dāng)商和余數(shù)與之前相同時(shí),即標(biāo)志著出現(xiàn)循環(huán)用p1、p2記錄位置,flag=1表示存在循環(huán) */ if(shang[j] == shang[i] && yushu[j] == yushu[i]){p1 = j;p2 = i;flag = 1;break;}}num = yushu[i] * 10;if(!num)//如果num被除盡,變?yōu)?,則沒有循環(huán){p1 = i + 1;break;}if(flag == 1){break;}}/*根據(jù) p1 的位置,如果沒有循環(huán),則建立完整鏈表;如果有循環(huán),則建立的是前綴。 */NODE *r = head;for (int i = 0; i < p1; i++){//尾插法建立鏈表NODE *q = (NODE*)malloc(sizeof(NODE));q->data = shang[i];q->next = NULL;r->next = q;r = q;}//補(bǔ)上循環(huán)if (flag == 1){NODE *r_save = r;for (int i = p1; i < p2; i++){NODE *q = (NODE*)malloc(sizeof(NODE));q->data = shang[i];q->next = NULL;r->next = q;r = q;}r->next = r_save->next;} }NODE * find( NODE *head, int *n ) {if(p2 > p1)//存在循環(huán){NODE *p = head->next;//初始化//計(jì)算長度*n = p2 - p1;//越過前綴for (int i = 0; i < p1; i++){p = p->next;}return p;}else//不存在循環(huán){*n = 0;return NULL;} }總結(jié)
- 上一篇: 七、一元多项式相乘
- 下一篇: 第六章-Hadoop优化与发展