1. 程式人生 > >Java&LeetCode 初入門——007. 整數反轉

Java&LeetCode 初入門——007. 整數反轉

Java&LeetCode 初入門——007. 整數反轉


文內程式碼全部採用JAVA語言。

題目描述

給出一個 32 位的有符號整數,你需要將這個整數中每位上的數字進行反轉。假設我們的環境只能儲存得下 32 位的有符號整數,則其數值範圍為 [−231,231 − 1]。請根據這個假設,如果反轉後整數溢位那麼就返回 0。

測試用例

示例 1:
輸入: 123
輸出: 321

示例 2:
輸入: -123 輸出: -321 示例 3: 輸入: 120 輸出: 21

個人解法

使用字串的翻轉

一開始看到這個題目的時候,首先想到的是用除法,取商或餘數,將數字一位一位的取出,然後再一位一位的翻轉,但是一時沒有想到快捷的辦法(由於個人知識有限,覺得不能避免迴圈),所以決定採用字串的翻轉。個人感覺這一題用python做會比較方便一點。

字串翻轉程式碼:

String 結果=new StringBuffer(待翻轉字串).reverse().toString();

結果由於各種各樣的原因,一直報錯。
首先是限制於輸入資料的正負,負號也會翻轉,於是考慮在字串反轉時採用絕對值;這樣就會導致第二個問題,−231

的絕對值不在int範圍之內。所以第一次嘗試時分成了三段。。。分別是0<=x<=2147483647,-2147483647<=x<=-1, x=-2147483648;但是很絕望,提交成功之後以53ms只打敗了19%,但好歹也是自己寫的,忍了。

想了想前兩段程式碼內部執行的內容其實差不多,決定把他們合併到一起,對絕對值求翻轉,然後再根據原來的值的大小,判斷正負。最終執行時間25ms,時間砍半,打敗了大概90%。給出程式碼如下:

class Solution {
	public int reverse(int x) {
		if (-2147483648<x &&
x<=2147483647) { int y=Math.abs(x); Integer a=new Integer(y); String b=a.toString(); String c=new StringBuffer(b).reverse().toString(); double d=Double.valueOf(c)*(y>x?-1:1); if (-2147483648<d && d<=2147483647) { return (int)d; } else { return 0; } } else { return 0; } } }

還有那段不成器的53ms程式碼,就不給出了。

官方解法

方法

彈出和推入數字 & 溢位前進行檢查

思路

我們可以一次構建反轉整數的一位數字。在這樣做的時候,我們可以預先檢查向原整數附加另一位數字是否會導致溢位。

演算法

反轉整數的方法可以與反轉字串進行類比。
我們想重複“彈出” xx 的最後一位數字,並將它“推入”到 \text{rev}rev 的後面。最後,\text{rev}rev 將與 xx 相反。
要在沒有輔助堆疊 / 陣列的幫助下 “彈出” 和 “推入” 數字,我們可以使用數學方法。
來自leetcode網站

class Solution {
    public int reverse(int x) {
        int rev = 0;
        while (x != 0) {
            int pop = x % 10;//餘數,也就是最後一位數
            x /= 10;//商取整,除最後一位的所有數
            if (rev > Integer.MAX_VALUE/10 || (rev == Integer.MAX_VALUE / 10 && pop > 7)) return 0;
            //有超出最大值的風險(檢查到倒數第二位,因為超出之後會報錯,要在報錯之前提前檢查是否有超出的風險)
            if (rev < Integer.MIN_VALUE/10 || (rev == Integer.MIN_VALUE / 10 && pop < -8)) return 0;
            //有超出最小值的風險
            rev = rev * 10 + pop;
        }
        return rev;
    }
}

學習完了感慨一下,666啊,我咋就沒想到。