[LeetCode] 7. 整數反轉:JavaScript 解法之溢出判斷你真的考慮全面了嗎?

題目連接: leetcode-cn.com/problems/re…git

方法一:數學方法

看到整數反轉這個題,最早聯想到先對數值取絕對值,而後除十取餘以對整數進行反轉,以後再考慮是否須要取負數以及數值範圍問題。github

/** * @param {number} x * @return {number} */
var reverse = function(x) {
    let result = 0;
    let value = Math.abs(x);
    while (value !== 0) {
        result = result * 10 + value % 10;
        value = Math.floor(value / 10);
    }
    result = x > 0 ? result : - result;
    return (result > Math.pow(2,31) - 1 || result < - Math.pow(2,31) ? 0 : result);
};
複製代碼
  • 時間複雜度:O(log(n))
  • 空間複雜度:O(1)

寫到這,本覺得就完成了,測試用例也都經過了。可是!你回想一下題目中的說明:微信

假設咱們的環境只能存儲得下 32 位的有符號整數。學習

咱們測試上面程序的時候並不是在這麼苛刻的環境下,因此先獲得 result,再判斷其是否在所要求的數值範圍內,不在則 return (0),因此也正常經過了全部的測試用例。可是當真正在一個只能存儲得下 32 位的有符號整數的環境中,若是整數反轉後的數值超過要求的數值範圍,那咱們根本得不到 result,由於會直接溢出。所以須要在整數反轉的時候就加上溢出判斷。測試

  1. 經過循環將數字 x 的每一位拆開,在進行整數反轉時,每一步都判斷是否溢出;
  2. 溢出條件有兩個,一個是大於整數最大值 MAX_VALUE,另外一個是小於整數最小值 MIN_VALUE,設當前計算結果爲 result,下一位爲 pop
  3. result * 10 + pop > MAX_VALUE 這個溢出條件來看:
    • 當出現 result > MAX_VALUE / 10 且還有 pop 須要添加時,則必定溢出;
    • 當出現 result === MAX_VALUE / 10pop > 7 時,則必定溢出,7 是 2^31 - 1 的個位數(2^31 - 1 = 2147483647)。
  4. result * 10 + pop < MIN_VALUE 這個溢出條件來看:
    • 當出現 result < MIN_VALUE / 10 且還有 pop 須要添加 時,則必定溢出;
    • 當出現 result === MIN_VALUE / 10pop < -8 時,則必定溢出,8 是 -2^31 的個位數(-2^31 = -2147483648)。
/** * @param {number} x * @return {number} */
var reverse = function(x) {
    let result = 0;
    let value = Math.abs(x);
    let MIN_VALUE = - Math.pow(2,31);
    let MAX_VALUE = Math.pow(2,31) - 1;
    while (value !== 0) {
        let pop = value % 10;
        // 溢出判斷
        if (result > MAX_VALUE / 10 || (result === MAX_VALUE / 10) && pop > 7) return 0;
        if (result < MIN_VALUE / 10 || (result === MIN_VALUE && pop < -8)) return 0;
        result = result * 10 + pop;
        value = Math.floor(value / 10);
    }
    return (x >= 0 ? result : - result);
};
複製代碼

方法二:JavaScript 的 reverse() 方法

可使用 JavaScript 的字符串轉換方法,但字符串轉換的效率較低且依賴 API,在 leetcode.com 上測試發現,所耗時間和內存均要大於方法一。ui

還有一個嚴重的問題就是,經過字符串轉換後乘以係數這一步驟 let ret = coefficient * str.split('').reverse().join('');,若是轉換後獲得的數值超出了題目要求的範圍,那這一步就已經溢出了,因此這種方法不適用。若是你有更好的方法,十分但願與你交流學習。spa

/** * @param {number} x * @return {number} */
var reverse = function(x) {
    let coefficient = x >= 0 ? 1 : -1;
    let str = Math.abs(x) + '';
    let ret = coefficient * str.split('').reverse().join('');
    return (ret > Math.pow(2, 31) -1 || ret < - Math.pow(2, 31) ? 0 : ret);
};
複製代碼

不知此處方法二的時間複雜度和空間複雜度如何計算,望獲得大佬的指導。code

更多題解

請關注:github.com/leviding/le…cdn

本人水平有限,歡迎交流分享你的想法,歡迎大佬批評指正。blog


掃描下方二維碼,關注微信公衆號「技術漫談」,訂閱更多精彩內容。

相關文章
相關標籤/搜索