題目描述
給你一個 32 位的有符号整數 x ,傳回将 x 中的數字部分反轉後的結果。
如果反轉後整數超過 32 位的有符号整數的範圍 [−231, 231 − 1] ,就傳回 0。
假設環境不允許存儲 64 位整數(有符号或無符号)。
示例:
輸入:x = 123
輸出:321
輸入:x = -123
輸出:-321
輸入:x = 120
輸出:21
輸入:x = 0
輸出:0
輸入:x = 1534236469
輸出:0
提示:
- -231 <= x <= 231 - 1
- 負數負号不反轉
- 反轉後第一位不為0
解答
一開始就想到了轉換為字元串暴力求解
我沒有一顆算法的心
,作為一個算法小白總是習慣性的暴力求解,主要是複雜的實在是一開始想不出來。還好暴力求解也做出來了(第一次交的還挂了。。),先看看我暴力求解的代碼(真的啰嗦-_-~)
暴力求解
知識點:
-
:可把一個 Number 對象轉換為一個字元串,并傳回結果。傳回的字元長度為1。toString()
- 文法:
NumberObject.toString(radix)
- 文法:
-
:可傳回指定位置的字元charAt()
- 文法:
stringObject.charAt(index)
- 文法:
-
:用于提取字元串中介于兩個指定下标之間的字元substring()
- 文法:
,第二個參數stringObject.substring(start,stop)
可選stop
- 說明:
方法傳回的子串包括substring()
處的字元,但不包括start
處的字元。stop
- 文法:
-
:用于把一個字元串分割成字元串數組split()
- 文法:
,第二個參數可選stringObject.split(separator,howmany)
- 說明:
- 傳回的數組中的字串不包括 separator 自身
- 如果把空字元串 ("") 用作 separator,那麼
中的每個字元之間都會被分割stringObject
- 文法:
-
:用于颠倒數組中元素的順序reverse()
- 文法:
arrayObject.reverse()
- 說明:該方法會改變原來的數組,而不會建立新的數組。
- 文法:
-
:用于把數組中的所有元素放入一個字元串join()
- 文法:
,參數可選arrayObject.join(separator)
- 說明:元素是通過指定的分隔符進行分隔的
- 文法:
var reverse = function(x) {
// 将x轉換為字元串
var str = x.toString();
// 判斷str在長度不為1的情況下最後一位是否為0
// 為0的話,反轉後第一位會是0
if (str.charAt(str.length-1) == '0' && str.length > 1) {
// 為0的話就舍棄
str = str.substring(0, str.length - 1);
}
// 去除負數的負号
str = x < 0 ? ("-" + str.substring(1).split("").reverse().join("")) : str.split("").reverse().join("");
// 對反轉後的數進行溢出判斷
if(str > Math.pow(2, 31) - 1 || str < Math.pow(-2, 31)) return 0;
return str;
}
其中遇到的問題:
上面提到過我第一次送出的時候挂了,是因為我是對
沒有反轉後的x進行溢出判斷
,而是判斷了反轉前的,但是反轉後的數會有溢出的可能
非暴力求解法
這個是Leecode上一位大佬寫的,跟我的比起來進階了不知道多少倍,真的巧妙。他的辦法是,通過取餘,位非運算符(~)來一個一個數取反
-
運算符(位非)用于對一個二進制操作數逐位進行取反操作~
- 第 1 步:把運算數轉換為 32 位的二進制整數。
- 第 2 步:逐位進行取反操作。
- 第 3 步:把二進制反碼轉換為十進制浮點數。
- 總的來說就是對數字進行取負運算,再減 1
- 那麼
,就是進行兩次取反~~
-
# 對 -12.2 進行位非運算,則傳回值為 -12 ~12 = -12-1 = -11.2 # 那麼 ~~12 = -(-13)-1 = -12 # 結論 ~~可以去掉小數
- 跟
不同的是,它隻是單純的去掉小數部分,不論正負都不會改變整數部分。Math.floor()
按照-12.2
的做法就會等于Math.floor()
-13
-
var reverse = function(x) {
let res = 0;
while(x){
res = res * 10 + x % 10;
if(res > Math.pow(2, 31) - 1 || res < Math.pow(-2, 31)) return 0;
x = ~~(x / 10);
}
return res;
};
代碼說明
:
- 每一次都利用取餘來獲得整數的最後一位,任何整數不管能不能除盡10,最後得到的餘數都是整數本身的最後一位
- 将反轉後的數存在res中,在通過
,然後res存的數位數提升,在通過res * 10
除10去掉小數,去掉x的最後一位。例如~~(x / 10)
- 開始x=123,res = 0
- 第一次x=123,res = 0 * 10+123 % 10 = 3,x=~~(123 / 10) = 12
- 第二次x=12,res = 3 * 10+12 % 10 = 30 + 2 = 32,x=~~(12 / 10) = 1
- 第三次x=1,res = 32 * 10+1 % 10 = 320 + 1 = 321,x=~~(1 / 10) = 0