好久沒練手了被卡在了這個題上,實在不應該...
不過分析的話這道題也是一個比較基礎的好題,特別是邊界條件判斷這方面。
題目描述:給定一個32位的帶符號整數,將其進行翻轉
連結:https://leetcode.com/problems/reverse-integer/description/
該問題需要考慮的點有:
1. 正負號
2. 尾數為零
3. 範圍(only hold integers within the 32-bit signed integer range)
該問題涉及到的考點(就當是考點)
1. integer 和 char 的相互轉換
2. 邊界條件涉及到的溢位問題【這個在除錯裡最慘...】
3. 在reverse的過程中,有負號和沒有負號的整數起始範圍不一
我的解決思路如下:
1)integer 轉 char 在C裡有sprintf 和 itoa, 但考慮到itoa並不是標準庫函式,可能會因為編譯情況不一存在問題,所以採用sprintf
該函式定義:
int sprintf( char *buffer, const char *format [, argument,…] );
將要轉換的引數列印到指定的buffer裡
e.g. sprintf(tmp,"%d",x);
將int的x 列印到tmp指向的陣列中
2)char 轉 integer在C中有標準庫函式atoi,直接呼叫即可。
3)正負號判定及尾數零
我在這裡對尾數零的情況解決的比較簡單粗暴,直接刪掉不要,從尾部開始,遇0則刪
正負號判斷就是看首部是否為"-",還比較簡單
4)邊界範圍判斷
32位整數最大是2147483647,直接判定是否有大於這個值就好。但這裡涉及到一個問題就是,在判定之前,我們已經將int轉為char 了,如果char 轉回來呢?當然這裡就很容易會因為reverse的緣故有溢位,就比較麻煩。
所以一個解決方案是將2147483647轉為str,然後strcmp:先看長度再比較每一位的ASCII
大概的解決思路就是這樣
我的思路不是最優的,如果存在什麼優化問題還請各位多多指點
C程式碼如下
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char tmp[64];
char* res;
int flag = 0;
int x,m;
scanf("%d",&x);
sprintf(tmp,"%d",x);
int n = strlen(tmp);
res = (char*)malloc(n*sizeof(char));
for(int j=n; j>1; j--){
if(tmp[j-1] != '0')break;
n--;
}
if(tmp[0] == '-'){
res[0] = tmp[0];
for (int i = 1; i < n; ++i){
res[i] = tmp[n-i];
}
}
else{
for(int i = 0; i < n; ++i){
res[i] = tmp[n-i-1];
}
}
int reverse;
char* cmp = "2147483647";
char* res1 = (char*)malloc(n*sizeof(char));
if(res[0] == '-'){
for(int j=0; j<n-1; j++){
res1[j] = res[j+1];
}
res1[n-1] = '\0';
}
else{
res1 = res;
}
if(strlen(res1)>strlen(cmp)){
//printf("bigger\n");
reverse = 0;
}
if(strlen(res1)<strlen(cmp)){
//printf("lower\n");
reverse = atoi(res);
}
if(strlen(res1) == strlen(cmp)){
if(strcmp(res1,cmp)>0){
//printf("big\n");
reverse = 0;
}
else{
reverse = atoi(res);
}
}
//printf("%d\n", reverse);
return 0;
}
複製程式碼
在discuss上找到一個短小精悍的解法,看來是我想的有點多....其實範圍可以縮小為int的問題,程式碼如下
int res = 0;
while (x) {
int temp = res * 10 + x % 10;
if (temp / 10 != res)
return 0;
res = temp;
x /= 10;
}
return res;
複製程式碼
檢查overflow的精髓在於if中,如果temp存在overflow,那麼temp / 10 和res的結果一定不一樣
程式碼來源如下:
另外學到的一點是,對於overflow 的處理,在C中其實是按照一個迴圈來的,比如說2147483648比最大上限2147483647多一個數,輸出的時候其實是-2147483648(感覺是個迴圈列表)