開題報告第一版寫完發給老師了,熬了兩周終於搞出來了,等着被懟了之后再改吧。晚上選了Leetcode一道簡單的題,整數反轉,就是將一個int類型的數反轉。原本確實很簡單,最后出現個問題有意思——整數溢出。
溢出
題目給出的要求是給出一個 32 位的有符號整數
,因此可以確定是int類型,但是32位int類型的范圍是[$-2^{31}, 2^{31}-1$], -2147483648-2147483647,那么問題來了,我提交代碼后,提示錯誤:
Exception in thread "main" java.lang.NumberFormatException: For input string: "9646324351"
意思就是無法將9646324351轉為int,很明顯給出的原始數字是1534236469,這是一個規范的int類型數值,然而反轉后9646324351很明顯超過了范圍。溢出了。當時我取巧了,既然是這個異常,直接在catch后return 0,機智如我,是個很人,提交,完美通過。
判斷整數溢出
說到底還是需要知道怎么做判斷啊,我的第一直覺是轉為BigDecimal,很明顯,這很方便且有效:
/**
* 方案二:轉為BigDecimal
*/
BigDecimal b = new BigDecimal(sb.toString());
if(b.compareTo(new BigDecimal(String.valueOf(Integer.MAX_VALUE))) > 0) {
// 溢出了
}else{
}
sb.toString()
就是需要判斷的字符串。
那么除了轉為BigDecimal,還有什么方式呢,肯定還有啦;
整數可以看作是相應位數上的數字做如下操作,比如123
- 0*10 + 1 = 1
- 1*10 + 2 = 12
- 12 * 10 + 3 = 123
每次增加10倍,並加上各位數字,因此可以在每一次sum*10+digit
之前做判斷。
if(Integer.MAX_VALUE/10 < sum || (Integer.MAX_VALUE/10 == sum && Integer.MAX_VALUE % 10 < digit)) {
// 說明溢出
return true;
}
完整判斷代碼如下:
private boolean outOfRange(String str) {
int length = str.length();
if(length == 0){
return false;
}
int index = 0;
int sum = 0; // 記錄累加結果
while(index < length) {
int digit = str.charAt(index) - '0';
// 這里假定str是合法的字符串,不需要進行digit合法性判斷
if(Integer.MAX_VALUE/10 < sum || (Integer.MAX_VALUE/10 == sum && Integer.MAX_VALUE % 10 < digit)) {
// 說明溢出
return true;
}
// 說明還沒有溢出
sum = sum * 10 + digit;
index ++;
}
return false;
}
參數str是需要判斷的字符串,這里沒有處理符號位,如果有-
直接去掉,按照Integer.MAX_VALUE
做比較同樣可以。同時函數也沒有考慮str中含有不合法的數字字符,重點關注溢出嘛。
LeetCode整數反轉
最后還是貼上整數反轉的代碼
package com.jiajia.m5;
import java.math.BigDecimal;
/**
* @ClassName: ReverseInteger
* @Author: fanjiajia
* @Date: 2019/5/17 下午8:00
* @Version: 1.0
* @Description:
*/
public class ReverseInteger {
public static void main(String[] args) {
ReverseInteger r = new ReverseInteger();
System.out.print(r.reverse(1534236469));
}
public int reverse(int x) {
if(x == 0) {
return 0;
}
char[] ch_arr = String.valueOf(x).toCharArray();
StringBuilder sb = new StringBuilder();
int end_index = ch_arr[0] == '-'? 1 : 0;
boolean flag = ch_arr[ch_arr.length - 1] == '0'; // 最后一位為0
for(int i = ch_arr.length - 1; i >= end_index; i--) {
if(flag && ch_arr[i] == '0') {
continue;
}
flag = false;
sb.append(ch_arr[i]);
}
/**
* 方案一:異常里面返回,也是夠了
*/
// int result;
// try {
// result = end_index == 1? -Integer.valueOf(sb.toString()) : Integer.valueOf(sb.toString());
// }catch(NumberFormatException e) {
// return 0;
// }
// return result;
/**
* 方案二:轉為BigDecimal
*/
// BigDecimal b = new BigDecimal(sb.toString());
// if(b.compareTo(new BigDecimal(String.valueOf(Integer.MAX_VALUE))) > 0) {
// return 0;
// }else{
// return end_index == 1? -Integer.valueOf(sb.toString()) : Integer.valueOf(sb.toString());
// }
/**
* 方案3:做溢出判斷
*/
if(outOfRange(sb.toString())) {
return 0;
}else {
return end_index == 1? -Integer.valueOf(sb.toString()) : Integer.valueOf(sb.toString());
}
}
private boolean outOfRange(String str) {
int length = str.length();
if(length == 0){
return false;
}
int index = 0;
int sum = 0; // 記錄累加結果
while(index < length) {
int digit = str.charAt(index) - '0';
// 這里假定str是合法的字符串,不需要進行digit合法性判斷
if(Integer.MAX_VALUE/10 < sum || (Integer.MAX_VALUE/10 == sum && Integer.MAX_VALUE % 10 < digit)) {
// 說明溢出
return true;
}
// 說明還沒有溢出
sum = sum * 10 + digit;
index ++;
}
return false;
}
}
有意思的是寫了個溢出判斷函數的效率還沒有直接catch異常來得高!!!
最后
研三畢業了,羡慕!!!
此致,敬禮!!!