大於一個數的最小回文數
阿新 • • 發佈:2019-01-28
如果直接對數n後面的每一個數進行判斷,那複雜度有可能很大。
解題思路還是從迴文數的構造出發。
分類討論如下:
A.該數的長度是奇數(特殊情況,只有1位的,除9外直接加1,9的話輸出11),取該數的前半截(包括中間數),
1.若該數是迴文數,則用前半截數值加1,之後再構造新的迴文數;
2.若不是迴文數,從中間往兩邊找到第一個不相等的數,若前面的小於後面的,則按1處理;
若前面的大於後面的,則直接用前半截來構造迴文數。
B.該數長度是偶數,取一半,後面的操作同奇數情況一樣。
void lagerSmallestPlalindrome(int n) { if (n < 0) { cout<<'0'<<endl; return; } char str[20]; char temp[15]; itoa(n,str,10); int len = strlen(str); if (len == 1) //長度為1 { if (n == 9) //若n為9 則最近迴文數為11 { cout<<"11"<<endl; } else //若n比9小 則為n+1 { cout<<n+1<<endl; } } else if (len%2 == 1) //長度大於1且為奇數 { for (int i = 0;i < len/2 + 1;++i) //儲存其前半部分 包括中間數 { temp[i] = str[i]; } temp[len/2 + 1] = '\0'; int i,j; for (i = len/2 -1 ,j = len/2 + 1;j < len;--i,++j) { if (str[i] != str[j]) { break; } } if (j == len||str[i] < str[j]) //n是迴文數 或不是迴文數但其前半部分小 { int num = atoi(temp); //則前半部分數值+1 再用前半部分構造迴文數 ++num; itoa(num,temp,10); cout<<num; for (int i = len/2 -1;i >= 0;--i) { cout<<temp[i]; } cout<<endl; } else //不是迴文數 但前半部分大 { cout<<temp; //則用前半部分構造迴文數 for (int i = len/2 - 1;i >= 0; --i) { cout<<temp[i]; } cout<<endl; } } else //長度大於1且為偶數 { for (int i = 0 ; i < len/2 ;++i) //儲存前半部分 { temp[i] = str[i]; } temp[len/2] = 0; if (str[len/2 - 1] == str[len/2]) //有可能是迴文數 { int i,j; for (i = len/2 - 1,j = len/2;j < len;++j,--i) { if (str[i] != str[j]) { break; } } if (j == len||str[i] < str[j]) //n是迴文數 或不是迴文數但其前半部分小 { //則前數加1 用前半部分構造 int num = atoi(temp); //則前半部分數值+1 再用前半部分構造迴文數 ++num; itoa(num,temp,10); cout<<num; for (int i = len/2 - 1;i >= 0;--i) { cout<<temp[i]; } cout<<endl; } else //不是迴文數但其前半部分大 { cout<<temp; //直接用前半部分構造 for (int i = len/2 - 1;i >= 0;--i) { cout<<temp[i]; } cout<<endl; } } else if (str[len/2 - 1] < str[len/2]) //中間靠前的數比後面的小 { //則前數加1 用前半部分構造 temp[len/2 - 1] = char(temp[len/2 - 1] + 1); cout<<temp; for (int i = len/2 - 1;i >= 0;--i) { cout<<temp[i]; } cout<<endl; } else //中間靠前的數比後面的大 { //則直接用前半部分構造 cout<<temp; for (int i = len/2 - 1;i >= 0;--i) { cout<<temp[i]; } cout<<endl; } } }
參考:1.http://www.cnblogs.com/itachi7/archive/2012/07/03/2574481.html