LeetCode題集-7 - 整數反轉
題目:給你一個 32 位的有符號整數 x ,返回將 x 中的數字部分反轉后的結果。如果反轉后整數超過 32 位的有符號整數的范圍 [?231, 231 ? 1] ,就返回 0。
假設環境不允許存儲 64 位整數(有符號或無符號)。

01、long類型字符串轉換法
雖然題目要求不允許使用64位整數,但是我們還是先使用最簡單最直觀的最符合思維邏輯的方式實現,然后以此打開思維尋找出更好的方法。
看到此題我第一反應就是直接把整數x轉為字符串,然后直接調用字符串方法反轉字符串,最后把反轉后的字符串轉換為long類型,同時比較是否再有效范圍內即可。
當然這是大致解題思路,其中還有許多細節需要處理。
首先需要處理負號問題,如果是負數我們需要取其絕對值,然后再反轉絕對值,而在取絕對值時需要注意int的最小值int.MinValue為-2147483648,而int.MaxValue最大值為2147483647,因此我們不能直接對int整數x直接取絕對值,而需要先把x轉為long類型整數,不然會報錯。
然后把絕對值反轉成字符數組,同時判斷正負號,如果是負數則需要在字符數組前加上負號’-’。
最后直接使用long.TryParse方法對字符數組進行轉換,同時判斷其有效范圍,并輸出結果,具體代碼如下:
//字符串long
public static int ReverseLongString(int x)
{
//是否為負數
var isNegative = x < 0;
//取絕對值,必須要先轉為long類型
//否則int.MinValue -2147483648會報錯
var abs = Math.Abs((long)x);
//把值轉為字符串并反轉,得到字符集合
var reversedChars = abs.ToString().Reverse();
if (isNegative)
{
//如果是負數則在字節數組前加入負號'-'
reversedChars = reversedChars.Prepend('-');
}
//轉換為long類型,并且是有效的int值,則返回結果
if (long.TryParse(reversedChars.ToArray(), out long result) && result >= int.MinValue && result <= int.MaxValue)
{
return (int)result;
}
return 0;
}
02、int類型字符串轉換法
既然題目中要求我們不能使用64位整數long類型,那么我們是否可以直接int類型進行轉換呢?
根據上一個解法,同樣的思路,我們先把int整數x轉為字符串,然后直接使用int.TryParse進行轉換即可。這樣可以利用轉換失敗過濾掉所有溢出的值。
具體實現代碼如下:
//字符串int
public static int ReverseIntString(int x)
{
//把值轉為字符串,并去掉負號'-',最后反轉,得到字符集合
var reversed = x.ToString().TrimStart('-').Reverse();
//轉換為int,成功則返回
if (int.TryParse(reversed.ToArray(), out int result))
{
//根據原始符號,返回結果
return x < 0 ? -result : result;
}
return 0;
}
03、數學方法
上面兩個方法本質還是通過字符串轉換,就效率來說是比較低的,因此我們可以通過數學計算的方式來實現其轉換。

如上圖,我們以把12345反轉為例,詳解講解反轉過程。
(1)通過12345%10,獲取到尾數字5,而尾數字又將作為新數值的首數字,新數值5;
(2)通過1234%10,獲取到尾數字4,新數值為5*10+4=54;
(3)通過123%10,獲取到尾數字3,新數值為54*10+3=543;
(4)通過12%10,獲取到尾數字2,新數值為543*10+2=5432;
(5)通過1%10,獲取到尾數字1,新數值為5432*10+1=54321;
其中還有一個重點是關于溢出的判斷,前兩個方法本質都是通過轉換方法觸發異常來攔截溢出,而在此方法中我們可以在實時計算的過程中直接判斷出是否溢出。
因為32位有符號整數x的取值范圍是-2147483648<=x<=2147483647,如果要保證反轉過來不溢出,則在處理到第九位的時候整個值應該在(-214748364,214748364)之間,不然結果肯定會溢出,而有效的int值首位數字最大為2,即使反轉過來也不可能大于7或小于-8,因此只需要判斷第九位數字是否合法即可完成溢出判斷。
具體實現代碼如下:
//數學方法
public static int ReverseMath(int x)
{
var result = 0;
while (x != 0)
{
//判斷溢出,因為輸入的是32位的有符號整數 x
//即輸入的 -2147483648<=x<=2147483647
//所以翻轉后的最后一位是1或2并不會導致溢出
//因此只需判斷九位數 > int.MaxValue / 10 或者 < int.MinValue / 10
if (result < int.MinValue / 10 || result > int.MaxValue / 10)
{
return 0;
}
//獲取當前末尾的數字
var digit = x % 10;
//去掉末尾數字
x /= 10;
//反轉并累積結果
result = result * 10 + digit;
}
return result;
}
04、基準測試
我們做個簡單的基準測試,分別對三種方法進行100萬次隨機生成整數值在范圍-2147483648至2147483647之間的值進行測試,得到如下結果。

通過上圖不難發現數學方法在整體性能方面遠遠高于字符串處理方式。
注:測試方法代碼以及示例源碼都已經上傳至代碼庫,有興趣的可以看看。https://gitee.com/hugogoos/Planner

浙公網安備 33010602011771號