字符串转换整数 (atoi)
题目描述:
请你来实现一个 atoi 函数,使其能将字符串转换成整数。
首先该函数会根据丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。
当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字组合起来,作为该整数的正负号;假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成整数。
该字符串除了有效的整数部分之后也可能会存在多余的字符,这些字符可以被忽略,它们对于函数不应该造成影响。
注意:
假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换。
在任何情况下,若函数不能进行有效的转换时,请返回 0。
说明:
假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231, 231 − 1]。如果数值超过这个范围,qing返回 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) 。
补充知识:
这一题考查的是正则化re模块的使用 https://blog.csdn.net/weixin_40583388/article/details/78458610
-
\d 匹配所有的数字
-
\D 匹配所有,但是数字除外
-
\s 空格
-
\S 匹配所有但是空格除外
-
\w 匹配所有的字母
-
\W 匹配所有但是字母除外 . 任意除换行符
-
\n . 表示点符号,斜杠本身是转义字符
常见的表达式举例:
- {1,3} 表示数字1到3范围
- “+” 匹配1个或者更多
- ?匹配0个或者1个结果
- “ * ” 匹配0个或者更多结果
- $ 匹配字符串的结尾部分
- ^ 匹配字符串的开始部分
- | 匹配左右表达式任意一个
- [] 字符集任意范围,例如[A-Z]表示大写A到Z
- {x} 计算一共找到x的数量
常用的元字符有以下几种
https://www.jianshu.com/p/95849a7df81c
.元字符:
pattm=re.compile('.',re.S) #re.s代表匹配的模式,我们这里选择了所有的匹配模式,所有换行符也会被匹配
pstr=pattm.findall('abcd1234\n')
if pstr!=None:
print(pstr)
else:
print('无匹配!')
>>> ['a', 'b', 'c', 'd', '1', '2', '3', '4', '\n']
. 代表一个任意的字符,这个字符默认包含所有的不包括换行符在内的所有字符,但通过改变匹配的模式,我们也可以做到匹配换行符,所有结果中返回了所有的匹配的结果!
^ 元字符:
pattm=re.compile('^abc',re.S) #匹配abc为开头的字符
pstr=pattm.findall('abcd1234\n')
if pstr!=None:
print(pstr)
else:
print('无匹配!')
>>> ['abc']
^ 号表示匹配开头,上面例子我们相当于匹配字符串abc,切记这里不是匹配到整个abc开头的字符串哦!
$ 元字符:
pattm=re.compile('abc$',re.S)
pstr=pattm.findall('abcd1234abc')
if pstr!=None:
print(pstr)
else:
print('无匹配!')
>>> ['abc']
$ 表示匹配结尾,上面例子就是相当于匹配abc,注意不是得到整个以abc结尾的字符串!
*元字符:
pattm=re.compile('a*',re.S) #找出所有0个a乃至n个a的匹配
pstr=pattm.findall('bcaacaaab')
if pstr!=None:
print(pstr)
else:
print('无匹配!')
>>> ['', '', 'aa', '', 'aaa', '', '']
*代表倍数,只对该符号前一个字符有效,可以是0倍也可以是任意倍数,所以上面结果中,返回了空字符,因为0倍就是空字符!!
+ 元字符:
pattm=re.compile('a+',re.S)
pstr=pattm.findall('bcaacaaab')
if pstr!=None:
print(pstr)
else:
print('无匹配!')
>>> ['aa', 'aaa']
元字符+和元字符*有点类似,只对该符号前一个字符有效,也是指重复,但是+不能匹配0倍,这是根本区别!
? 元字符:
pattm=re.compile('ca?t',re.S)
pstr=pattm.findall('catdddct')
if pstr!=None:
print(pstr)
else:
print('无匹配!')
>>> ['cat', 'ct']
元字符?号也是重复类字符,但他表示可选,上面例子中a字符表示可选字符,他可匹配也可以不匹配,所以返回了两种匹配结果!
{ } 元字符:
元字符{} 也是重复字符中的一员,只对该符号前一个字符有效,他比+和*更加的灵活
pattm=re.compile('a{1,2}',re.S) #最少匹配1个a,最多匹配两个a
pstr=pattm.findall('fcabcdaaaef^')
if pstr!=None:
print(pstr)
else:
print('无匹配!')
>>> ['a', 'aa', 'a']
{}字符中可以有两个变量{m,n}, m表示最少的匹配倍数,n表示最大的匹配倍数.也可以只写一个变量{n},表示最大匹配n倍字符!
[] 元字符:
pattm=re.compile('[abc]',re.S)
pstr=pattm.findall('abcdef')
if pstr!=None:
print(pstr)
else:
print('无匹配!')
>>> ['a', 'b', 'c']
元字符[] 表示一个范围,相当于指定匹配一个范围类的字符,上图中想到与能匹配a,b,c三个字符范围,也可以写成[a-b]两者的效果相同,很多手机号的正则就是利用了该元字符,比如[0-9]取0到9范围内的一个数字!
还需要特别注意一点的是,在[]类中其他元字符将不会再有原有功能!
举个例子:
pattm=re.compile('[abc^]',re.S) #按道理,^表示匹配开头,应该匹配abc开头的字符
pstr=pattm.findall('fcabcdef^')
if pstr!=None:
print(pstr)
else:
print('无匹配!')
>>> ['c', 'a', 'b', 'c', '^'] #但结果却可以看出,因为[]类的原因,^元字符的作用消失了,被当成了普通的一个字符,返回了所有[]内字符范围的匹配
>**\ 元字符:**
\字符是一个比较有意思的字符,他主要有两种功能
一种是转义:
pattm=re.compile('\{',re.S) #将{转义成普通字符匹配
pstr=pattm.findall('fc{aa{ef[')
if pstr!=None:
print(pstr)
else:
print('无匹配!')
>>> ['{', '{']
我们可以通过\将其他的元字符当成普通字符来匹配!
第二种是组合序列,通过一些特定的组合,组合成了一些特定功能的序列,比如我们上面提到的特殊序列\s,\w等
| 元字符:
\字符是一个比较有意思的字符,他主要有两种功能
一种是转义:
pattm=re.compile('a|b',re.S)
pstr=pattm.findall('abcdbcda')
if pstr!=None:
print(pstr)
else:
print('无匹配!')
>>> ['a', 'b', 'b', 'a']
| 字符和java中的或有点类似,表示匹配前面部分或者后面部分,需要注意的是整个前面和后面部分!假如上面例子是abc|a表达式,表示匹配abc或者b,而不是先匹配ab,然后在c|a中选择一个,这种理解是错误的!
( ) 元字符:
()字符代表分组,代表一个整体
pattm=re.compile('(abc)',re.S) #代表匹配abc字符
pstr=pattm.findall('abcccababab')
if pstr!=None:
print(pstr)
else:
print('无匹配!')
>>> ['abc']
当然()的用法远远不止上面这么简单,我们可以在()中加入任何的一个匹配规则组成一个组,就可以实现无数种功能
比如:
pattm=re.compile('(^abc.+)',re.S)
pstr=pattm.findall('abcccababab')
if pstr!=None:
print(pstr)
else:
print('无匹配!')
>>> ['abcccababab']
上面’(^abc.+)’ 正则,如果你认真看了上面所有的元字符,应该不难理解,表示匹配abc开头的任意长度的字符串,所以上面返回了整个字符串.
还有一点需要注意,记得最上面我们使用match和search函数的时候,往往打印都会使用group函数,入下:
pattm=re.compile('(^abc.+)',re.S)
pstr=pattm.search('abcccababab')
if pstr!=None:
print(pstr.group()) #使用过了group函数
else:
print('无匹配!')
其实这里的group函数对应的就是一个正则中的()组,group(1)代表第一个出现的()组的匹配,groupe(1,3)代表出现的第1个和第三个()组的匹配!
解题思路:
- 第一步是利用strip()函数来使字符串去空格
- 第二步判断字符串的首位是否是数字或者是+/-号
- 第三步将尽可能多的整数字符加入,知道出现空格或者是非数字字符
Python源码:
class Solution:
def myAtoi(self, str: str) -> int:
# 导入正则模块
import re
# 字符串中查找全部符合条件的整数,返回的是列表,第一个参数是正则,第二个参数是字符串
# strip()字符串去空格
ret = re.findall(r"^[-+]?\d+", str.strip())
# 判断是否有匹配的值,没有的话返回0,例如"word values 987",匹配不到,返回0
if ret:
ret_str = ret[0] # 匹配的数字的字符串
ret_str2 = "" # 记录去符号的字符串,ret_str后面还要使用,所以定义一个新的变量记录
# 判断是否带有符号 + or -
if ret_str[0] == "-" or ret_str[0] == "+":
ret_str2 = ret_str[1:]
else:
ret_str2 = ret_str
# str转int
ret_int = int(ret_str2)
# 判断第一个字符是否为负号
if ret_str[0] == "-":
# 三目运算符,判断是否溢出
# 如果ret_int <= 2**31则返回-ret_int,否则返回-2**31
return -ret_int if ret_int <= 2 ** 31 else -2 ** 31
else:
return ret_int if ret_int < 2 ** 31 else 2 ** 31 - 1
else:
return 0
欢迎关注我的github:https://github.com/UESTCYangHR