[數學、棧] 整數反轉

題目描述

給出一個 32 位的有符號整數,你需要將這個整數中每位上的數字進行反轉。

假設我們的環境只能存儲得下 32 位的有符號整數,則其數值範圍爲 [-2^{31}, 2^{31} - 1]。請根據這個假設,如果反轉後整數溢出那麼就返回 0。

數據樣例

輸入: 123    輸出: 321

輸入: -123    輸出: -321

輸入: 120    輸出: 21

算法分析

如果是一個字符串,怎麼反轉?使用棧思想,字符順序入棧再出棧,就能得到反轉的字符串。

數字也是同理的,使用棧思想,但是多一步溢出的考慮。

每一位的數字入棧、出棧的過程,可以用代碼表示爲

// x是原數字,rev是反轉後的數字
int x, rev;

// 入棧
int pop = x % 10;
x /= 10;

// 出棧
int temp = rev * 10 + pop; // 這裏有溢出的可能
rev = temp;

可以看到,最後的出棧過程存在溢出的可能性。

處理溢出問題,有兩種思路:

  1. 找出正負數各自溢出的臨界點
  2. 利用溢出特性進行反向驗證,語言不好解釋,看代碼更清晰

思路一

找出溢出的臨界點,正負數溢出臨界點分別是:

// 正數溢出臨界點
rev == Integer.MAX_VALUE / 10 && pop > Integer.MAX_VALUE % 10

// 負數溢出臨界點
rev == Integer.MIN_VALUE / 10 && x < Integer.MIN_VALUE % 10

算法代碼:

public int reverse(int x) {
    int rev = 0;
    while (x != 0) {
        int pop = x % 10;
        // 正數溢出臨界點
        if (rev > Integer.MAX_VALUE / 10 || (rev == Integer.MAX_VALUE && pop > Integer.MAX_VALUE % 10))
            return 0;
        // 負數溢出臨界點
        if (rev < Integer.MIN_VALUE / 10 || (rev == Integer.MIN_VALUE && pop > Integer.MIN_VALUE % 10))
            return 0;
        x /= 10;
        rev = rev * 10 + pop;
    }
    return rev;
}

思路二

數字計算溢出後得到的結果,再除以 10 是不能得到原值的。

算法代碼:

public int reverse(int x) {
    int reverse = 0;
    while (x != 0) {
        int temp = reverse * 10 + x % 10;
        if (temp / 10 != reverse) return 0;// 利用的溢出特性反向驗證
        reverse = temp;
        x /= 10;
    }
    return reverse;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章