welcome to my blog
剑指offer面试题67(java版):把字符串转成整数
题目描述
将一个字符串转换成一个整数(实现Integer.valueOf(string)的功能,但是string不符合数字要求时返回0),要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0。
输入描述:
输入一个字符串,包括数字字母符号,可以为空
输出描述:
如果是合法的数值表达则返回该数字,否则返回0
示例1
输入
+2147483647
1a33
输出
2147483647
0
class Solution {
public int strToInt(String str) {
str = str.trim();
if(str.equals("")){
return 0;
}
int n = str.length();
int p = 0;
char[] chs = str.toCharArray();
int res = 0;
int flag = 1;
if(chs[p]=='-'){
flag = -1;
p++;
}else if(chs[p]=='+'){
p++;
}
for(; p<n; p++){
char ch = chs[p];
if(ch>='0' && ch<='9'){
//溢出判断
if(flag==1){
//res * 10 + cur > max
if(res>(Integer.MAX_VALUE - (ch-'0'))/10){
return Integer.MAX_VALUE;
}
}else{
//-res * 10 - cur < min
if(-res<(Integer.MIN_VALUE + ch - '0')/10){
return Integer.MIN_VALUE;
}
}
res = res*10 + ch - '0';
}else{
break;
}
}
return res*flag;
}
}
第三次做; 这道题真的好! 核心: 1)int越界处理
/*
难点: 字符串形式下考虑越界
int范围[-2147483648, 2147483647]
什么情况下会越界? 复现一下我开始复杂的处理
关于正数
cur == 214748364时, 下一个数字的取值范围只能是[0,7], 其他数字都会导致越界
cur > 214748364时, 如果后面还有数字则会越界
关于负数
cur == -214748364时, 下一个数字的取值范围只能是[0,8], 其他数字都会导致越界
cur < -214748364时, 如果后面还有数字则会越界
上面的处理不好,下面的写法好!
对于正数
res*10 + cur > max
res > (max-cur)/10时越界
对于负数
-res*10 - cur < min
res > -(min + cur)/10
*/
class Solution {
public int strToInt(String str) {
if(str==null || str.length()==0)
return 0;
int index=0;
int n = str.length();
int res=0;
char ch;
//跳过空格; 细节: 对索引进行越界检查
while(index<n && (ch = str.charAt(index))==' ')
index++;
//here, index==n || ch!=' '
if(index==n)
return res;
//确定正负号
boolean positive = true;
ch = str.charAt(index);
if(ch=='-'){
positive = false;
index++;
}
else if(ch=='+'){
positive = true;
index++;
}
else if(ch<'0' || ch>'9')
return res;
//统计数字
if(index==n)
return res;
while(index<n){
ch = str.charAt(index);
if(ch<'0' || ch>'9')
//感觉还是用正负一表示比boolean方便
return positive?res:-res;
int cur = ch-'0';
//检查正数是否越界
if(positive && res > (Integer.MAX_VALUE - cur)/10)
return Integer.MAX_VALUE;
//检查负数是否越界; 这么写有风险, 如果cur为0那么-(Integer.MIN_VALUE + cur)就会越界, 所以先除以10, 再取负号
else if(res > -((Integer.MIN_VALUE + cur)/10))
return Integer.MIN_VALUE;
//update
res = res*10 + cur;
index++;
}
return positive?res : -res;
}
}
思路
- 见注释
- 关键在于如何判断上溢和下溢
第二次做, 单独处理第一个字符; 检查上溢和下溢
上溢发生的条件
10*res + curr > max
判断时得写成res > (max - curr) / 10
因为10*res + curr上溢的话就程序就在这里报错了
res > (2147483647 - curr) / 10
假设res = 2147483640, 如果curr=0,1,2,3,4,5,6,7都不会发生溢出
但是curr>=8时,上面的不等式成立,说明发生上溢
下溢发生的条件
-10*res - curr < min
res > (min + curr) / 10
res > -(-2147483648 + curr) / 10
假设res = 2147483640, 如果curr=0,1,2,3,4,5,6,7,8都不会发生下溢
但是curr>=9时,上面的不等式成立,说明发生下溢
public class Solution {
public int StrToInt(String str) {
if(str==null || str.length()==0)
return 0;
int flag=1, res=0;
//first char
if(str.charAt(0)=='+')
flag=1;
else if(str.charAt(0)=='-')
flag=-1;
else if(str.charAt(0)<'0' || str.charAt(0)>'9')
return 0;
else
res = str.charAt(0) - '0';
//other chars
for(int i=1; i<str.length(); i++){
if(str.charAt(i)<'0' || str.charAt(i) > '9')
return 0;
//检查是否上溢
else if(flag==1 && res > (Integer.MAX_VALUE - (str.charAt(i)-'0'))/10)
return 0;
//检查下溢
else if(flag==-1 && res > -(Integer.MIN_VALUE + (str.charAt(i)-'0'))/10)
return 0;
else
res = 10*res + str.charAt(i)-'0';
}
return flag*res;
}
}
第二次做, 先处理第一个字符,再统一处理剩下的字符; char-‘0’; 字符串求和问题一定要记得检查溢出,因为字符串可以表示的数的大小远超整数类型的最大值
public class Solution {
public int StrToInt(String str) {
if(str==null || str.length()==0)
return 0;
//
int flag = 1;
int res = 0;
if(str.charAt(0)=='+')
flag=1;
else if(str.charAt(0)=='-')
flag=-1;
else if(str.charAt(0)<'0' || str.charAt(0)>'9')
return 0;
else res += 10*res + str.charAt(0) - '0';
for(int i=1; i<str.length(); i++){
if(str.charAt(i)<'0' || str.charAt(i) > '9')
return 0;
res = 10*res + str.charAt(i) - '0';
}
return res*flag;
}
}
public class Solution {
public int StrToInt(String str) {
/*
思路:
x - '0'
要把特殊情况考虑全面: 空字符串, 只有正负号, 上溢, 下溢
因为要求不合法数值均返回0, 所以把返回值初始化为0很方便
*/
int flag=1, sum=0; // sum初始化为0很有用, 因为要求不合法数值均返回0
for(int i=0; i<str.length(); i++){
if(str.charAt(i)=='+')
flag=1;
else if(str.charAt(i)=='-')
flag=-1;
else if(str.charAt(i) < '0' || str.charAt(i) > '9')
return 0;
else if(flag==1 && (str.charAt(i) - '0' > Integer.MAX_VALUE - 10*sum)) //检查上溢
return 0;
else if(flag==-1 && (str.charAt(i) - '0' - 1> Integer.MAX_VALUE - 10*sum )) //检查下溢
return 0;
else
sum = 10* sum + str.charAt(i) - '0';
}
return flag*sum;
}
}