请你来实现一个 myAtoi(string s) 函数,使其能将字符串转换成一个 32 位有符号整数(类似 C/C++ 中的 atoi 函数)。
函数 myAtoi(string s) 的算法如下:
读入字符串并丢弃无用的前导空格
检查下一个字符(假设还未到字符末尾)为正还是负号,读取该字符(如果有)。 确定最终结果是负数还是正数。 如果两者都不存在,则假定结果为正。
读入下一个字符,直到到达下一个非数字字符或到达输入的结尾。字符串的其余部分将被忽略。
将前面步骤读入的这些数字转换为整数(即,"123" -> 123, "0032" -> 32)。如果没有读入数字,则整数为 0 。必要时更改符号(从步骤 2 开始)。
如果整数数超过 32 位有符号整数范围 [−231, 231 − 1] ,需要截断这个整数,使其保持在这个范围内。具体来说,小于 −231 的整数应该被固定为 −231 ,大于 231 − 1 的整数应该被固定为 231 − 1 。
返回整数作为最终结果。
注意:
本题中的空白字符只包括空格字符 ' ' 。
除前导空格或数字后的其余字符串外,请勿忽略 任何其他字符。
来源:力扣(LeetCode)链接:https://leetcode.cn/problems/string-to-integer-atoi
佬的思路
通过设定i移动字符下标,t为对应数,sign为判断正负,解析为整数用的是ASCII码来获取的,再设定边界条件输出。
C语言:
作者:exciting-shamirbdu链接:https://leetcode.cn/problems/string-to-integer-atoi/solution/cyu-yan-shi-xian-dai-ma-ji-jian-ban-by-e-gxsg/
intmyAtoi(char*s){
inti,sign=0,t=0;
for(i=0;s[i]==' ';i++) continue;
if(s[i]=='-'||s[i]=='+') sign=s[i++]=='-'?1:0;
for(;s[i]>='0'&&s[i]<='9'&&t>-2147483648;i++){
if((t==-214748364&&s[i]>'8')||t<-214748364) t=-2147483648;
elset=t*10-(s[i]-'0');
}
if(sign) returnt;
return (t==-2147483648)?2147483647:-t;
}
//时间 0ms,空间5.5MB
Java:
这个问题其实没有考察算法的知识,模拟的是日常开发中对于原始数据的处理(例如「参数校验」等场景),如果面试中遇到类似的问题,应先仔细阅读题目文字说明和示例,有疑惑的地方和需要和面试官确认,在编码的时候需要耐心和细心地调试。
其实很多时候,业务需求就是类似这样的问题,工作中如果遇到:
1、有现成的工具和类库需尽量使用,因为它们是性能更优,且经过更严格测试,是相对可靠的;2、能抽取成工具类、工具方法的尽量抽取,以突出主干逻辑、方便以后代码复用;3、不得不写得比较繁琐、冗长的时候,需要写清楚注释、体现逻辑层次,以便上线以后排查问题和后续维护。
在这里我罗列几个要点:
根据示例 1,需要去掉前导空格;
根据示例 2,需要判断第 1 个字符为 + 和 - 的情况,因此,可以设计一个变量 sign,初始化的时候为 1,如果遇到 - ,将 sign 修正为 -1;
判断是否是数字,可以使用字符的 ASCII 码数值进行比较,即 0 <= c <= '9';
根据示例 3 和示例 4 ,在遇到第 1 个不是数字的字符的情况下,转换停止,退出循环;
根据示例 5,如果转换以后的数字超过了 int 类型的范围,需要截取。这里不能将结果 res 变量设计为 long 类型,注意:由于输入的字符串转换以后也有可能超过 long 类型,因此需要在循环内部就判断是否越界,只要越界就退出循环,这样也可以减少不必要的计算;
由于涉及下标访问,因此全程需要考虑数组下标是否越界的情况。
特别注意:
1、由于题目中说「环境只能保存 32 位整数」,因此这里在每一轮循环之前先要检查乘以 1010 以后是否溢出,具体细节请见编码。
2、Java 、Python 和 C++ 字符串的设计都是不可变的,即使用 trim() 会产生新的变量,因此我们尽量不使用库函数,使用一个变量 index 去做遍历,这样遍历完成以后就得到转换以后的数值。
作者:liweiwei1419链接:https://leetcode.cn/problems/string-to-integer-atoi/solution/jin-liang-bu-shi-yong-ku-han-shu-nai-xin-diao-shi-/来源:力扣(LeetCode)
publicclassSolution {
publicintmyAtoi(Stringstr) {
intlen=str.length();
// str.charAt(i) 方法回去检查下标的合法性,一般先转换成字符数组
char[] charArray=str.toCharArray();
// 1、去除前导空格
intindex=0;
while (index<len&&charArray[index] ==' ') {
index++;
}
// 2、如果已经遍历完成(针对极端用例 " ")
if (index==len) {
return0;
}
// 3、如果出现符号字符,仅第 1 个有效,并记录正负
intsign=1;
charfirstChar=charArray[index];
if (firstChar=='+') {
index++;
} elseif (firstChar=='-') {
index++;
sign=-1;
}
// 4、将后续出现的数字字符进行转换
// 不能使用 long 类型,这是题目说的
intres=0;
while (index<len) {
charcurrChar=charArray[index];
// 4.1 先判断不合法的情况
if (currChar>'9'||currChar<'0') {
break;
}
// 题目中说:环境只能存储 32 位大小的有符号整数,因此,需要提前判:断乘以 10 以后是否越界
if (res>Integer.MAX_VALUE/10|| (res==Integer.MAX_VALUE/10&& (currChar-'0') >Integer.MAX_VALUE%10)) {
returnInteger.MAX_VALUE;
}
if (res<Integer.MIN_VALUE/10|| (res==Integer.MIN_VALUE/10&& (currChar-'0') >-(Integer.MIN_VALUE%10))) {
returnInteger.MIN_VALUE;
}
// 4.2 合法的情况下,才考虑转换,每一步都把符号位乘进去
res=res*10+sign* (currChar-'0');
index++;
}
returnres;
}
publicstaticvoidmain(String[] args) {
Solutionsolution=newSolution();
Stringstr="2147483646";
intres=solution.myAtoi(str);
System.out.println(res);
System.out.println(Integer.MAX_VALUE);
System.out.println(Integer.MIN_VALUE);
}
}
总结:
这道题题目给得很充分,我开始想的是用指针移动到数字,可是想了半天怎么也不知道如何转字符串,看了大佬的代码后,才知道用ASCII码来来解析,发现自己怎么这么蠢,后面的限定范围自己弄得不太懂,临界值处一直失败。int类型在内存中占用了4个字节,也就是32位。int类型是有符号的,因此,32位并不会全部用来存储数据,使用最高位来存储符号,最高位是0,提示数据是正数,最高位是1,表示数据是负数,使用其他的31位来存储数据。
收获:
ASCII码
学习链接:
ASCII码-https://www.asciim.cn/