目录
刷题日期:下午5:01 2021年5月28日星期五
个人刷题记录,代码收集,来源皆为leetcode
经过多方讨论和请教,现在打算往Java方向发力
主要答题语言为Java
题目:
剑指 Offer 67. 把字符串转换成整数
难度中等86
写一个函数 StrToInt,实现把字符串转换成整数这个功能。不能使用 atoi 或者其他类似的库函数。
首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。
当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字组合起来,作为该整数的正负号;假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成整数。
该字符串除了有效的整数部分之后也可能会存在多余的字符,这些字符可以被忽略,它们对于函数不应该造成影响。
注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换。
在任何情况下,若函数不能进行有效的转换时,请返回 0。
说明:
假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231, 231 − 1]。如果数值超过这个范围,请返回 INT_MAX (231 − 1) 或 INT_MIN (−231) 。
示例 1:
输入: "42"
输出: 42
示例 2:
输入: " -42"
输出: -42
解释: 第一个非空白字符为 '-', 它是一个负号。
我们尽可能将负号与后面所有连续出现的数字组合起来,最后得到 -42 。
示例 3:
输入: "4193 with words"
输出: 4193
解释: 转换截止于数字 '3' ,因为它的下一个字符不为数字。
示例 4:
输入: "words and 987"
输出: 0
解释: 第一个非空字符是 'w', 但它不是数字或正、负号。
因此无法执行有效的转换。
示例 5:
输入: "-91283472332"
输出: -2147483648
解释: 数字 "-91283472332" 超过 32 位有符号整数范围。
因此返回 INT_MIN (−231) 。
题目分析
题目也太长了,感觉不太能理解,学习他人
初始解答:
平均40行起的代码,还是饶了我吧,这种题真的会出吗,学习K神
class Solution {
public int strToInt(String str) {
int res = 0, bndry = Integer.MAX_VALUE / 10;
int i = 0, sign = 1, length = str.length();
if(length == 0) return 0;
while(str.charAt(i) == ' ')
if(++i == length) return 0;
if(str.charAt(i) == '-') sign = -1;
if(str.charAt(i) == '-' || str.charAt(i) == '+') i++;
for(int j = i; j < length; j++) {
if(str.charAt(j) < '0' || str.charAt(j) > '9') break;
if(res > bndry || res == bndry && str.charAt(j) > '7')
return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
res = res * 10 + (str.charAt(j) - '0');
}
return sign * res;
}
}
执行结果:通过
显示详情 添加备注
执行用时:2 ms, 在所有 Java 提交中击败了99.42%的用户
内存消耗:38.6 MB, 在所有 Java 提交中击败了11.47%的用户
学习他人:
方法一:
(编辑过)2020-04-11
class Solution {
public int strToInt(String str) {
//先去空格再判空,不然" "教您做人,血的教训
str = str.trim();
if(str.length() == 0){
return 0;
}
//然后我想啊,下面要判断首位了
//首位合格的无非就'+'或'-'或数字三种情况,其他的一概滚蛋
//'+''-'肯定是要把它去掉的,这样三种情况就统一了
//当然了,'-abc'这种有可能出现,不过只看首位它是没毛病的
//让它进来,反正后面很容易解决
//既然要去掉正负号,那肯定要出个boolean记一下是不是负数
boolean isMinus = false;
char[] ch = str.toCharArray();
//首位是不是正负号或者数字啊
if(ch[0] == '+' || ch[0] == '-' || Character.isDigit(ch[0])){
//是不是正负号啊
if(ch[0] == '+' || ch[0] == '-'){
//是不是负号啊
if(ch[0] == '-'){
isMinus = true;
}
//删除首位
ch = Arrays.copyOfRange(ch,1,ch.length);
}
//首位搞定了就看后面是不是数字了,直到不是数字的地方或者倒底结束
int index = 0;
//结果可能超int范围,拿个long接一下
//'-abc'这种情况返回的也是0,舒服,一箭双雕
long res = 0;
//短路与助您远离空指针喔,铁汁们,先后顺序关注一下
while(index < ch.length && Character.isDigit(ch[index])){
//一位一位往上算
res *= 10;
res += ch[index] - '0';
//及时止损,一看到res超int范围立马return
//你要是想着最后一起算,那肯定会有超long范围的测试用例等着你,你就哭去吧
if(res > Integer.MAX_VALUE){
//正负号看是正数负数,返回最大值
return isMinus ? Integer.MIN_VALUE : Integer.MAX_VALUE;
}
//别忘了往后走一位
index++;
}
//long转int就是这么朴实无华
return isMinus ? -(int)res : (int)res;
}
//兄弟首位都不对想啥呢,回去吧您
return 0;
}
}
方法二:
Plius 6 小时前 java做法,时间n空间1
class Solution {
public int strToInt(String str) {
//符号位type
boolean type = true;
if(str.length() == 0) return 0;
//len检索数字字符串中所要求数字的最后一位(最低位),index检索数字的最高位
int len = 0, index = 0;
//pass空格
while(len < str.length() && str.charAt(len) == ' ') len++;
if(len == str.length()) return 0;
//符号位判断 true+ false-
if(str.charAt(len) == '-'){
type = false;
len++;
}else if(str.charAt(len) == '+') len++;
//符号位后的高位0无用,直接pass
while(len < str.length() && str.charAt(len) == '0') len++;
//index检索有效最高位
index = len;
//若有效最高位不为数字或为0直接返回0
if(len >= str.length() || str.charAt(len) < '0' || str.charAt(len) > '9') return 0;
//len检索有效最低位
while(len < str.length() && str.charAt(len) >= '0' && str.charAt(len) <= '9') len++;
//MAX 2147483647 MIN -2147483648 长度均为10位,若数字有效长度超过10则直接根据type类型返回
if(len - index > 10) return type? Integer.MAX_VALUE: Integer.MIN_VALUE;
//进行数据检索,从有效最低为len检索到有效最高位index
len--;
//temp用于自乘10,num返回最终结果
int temp = 1, num = 0;
while(len >= index){
//如果temp为1000000000,则代表有效数字长度为10,据此判断是否超过int范围
//前面已经pass掉有效数字长度大于10的情况了
if(temp == 1000000000){
//最高位大于2,已超过int范围
if(str.charAt(len) > '2') return type? Integer.MAX_VALUE: Integer.MIN_VALUE;
else if(str.charAt(len) == '2'){
//最高位为2,根据上一循环num大小判断是否超过int范围
if(type){
if(num > 147483647) return Integer.MAX_VALUE;
}else{
if(num > 147483648) return Integer.MIN_VALUE;
}
}
}
//int范围内的操作
num += (str.charAt(len) - '0') * temp;
len--;
temp *= 10;
}
//根据符号位返回
if(!type) return -num;
return num;
}
}
方法三:
FalseBlank
2021-05-03
这题直接把我中等提交正确率拉下来几个百分点
class Solution {
public int strToInt(String str) {
int n = str.length();
long num = 0;
boolean bl = false;
int start = 0;
while(start < n && str.charAt(start) == ' '){
start++;
}
if(n == 0 || start == n) return 0;
if(str.charAt(start) == '-'){
bl = true;
start++;
}else if(str.charAt(start) == '+'){
start++;
}else if(!Character.isDigit(str.charAt(start))){
return 0;
}
if(start == n) return 0;
int i = start;
char c = str.charAt(start);
if(Character.isDigit(c)){
while(i < n){
c = str.charAt(i);
if(!Character.isDigit(c)) break;
int j = c - '0';
num = num * 10 + j;
if(num > Integer.MAX_VALUE){
return bl ? Integer.MIN_VALUE : Integer.MAX_VALUE;
}
i++;
}
}else{
return 0;
}
return bl ? (int)(-num) : (int)num;
}
}
方法四:
K神 根据题意,有以下四种字符需要考虑:
首部空格 符号位 非数字字符 数字字符 字符转数字 数字拼接
作者:jyd
链接:https://leetcode-cn.com/problems/ba-zi-fu-chuan-zhuan-huan-cheng-zheng-shu-lcof/solution/mian-shi-ti-67-ba-zi-fu-chuan-zhuan-huan-cheng-z-4/
来源:力扣(LeetCode)
数字越界处理:
class Solution {
public int strToInt(String str) {
char[] c = str.trim().toCharArray();
if(c.length == 0) return 0;
int res = 0, bndry = Integer.MAX_VALUE / 10;
int i = 1, sign = 1;
if(c[0] == '-') sign = -1;
else if(c[0] != '+') i = 0;
for(int j = i; j < c.length; j++) {
if(c[j] < '0' || c[j] > '9') break;
if(res > bndry || res == bndry && c[j] > '7') return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
res = res * 10 + (c[j] - '0');
}
return sign * res;
}
}
若不使用 trim() / strip()
方法,而从头开始遍历字符串,则可以将空间复杂度降低至 O(1),代码如下:
class Solution {
public int strToInt(String str) {
int res = 0, bndry = Integer.MAX_VALUE / 10;
int i = 0, sign = 1, length = str.length();
if(length == 0) return 0;
while(str.charAt(i) == ' ')
if(++i == length) return 0;
if(str.charAt(i) == '-') sign = -1;
if(str.charAt(i) == '-' || str.charAt(i) == '+') i++;
for(int j = i; j < length; j++) {
if(str.charAt(j) < '0' || str.charAt(j) > '9') break;
if(res > bndry || res == bndry && str.charAt(j) > '7')
return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
res = res * 10 + (str.charAt(j) - '0');
}
return sign * res;
}
}
总结
以上就是本题的内容和学习过程了,字符串转义,点到为止。
欢迎讨论,共同进步。