题目:力扣
1. 验证是否为回文串
给定一个字符串 ,包含空字符串, 数字,英文字符,以及各种符号
s = "A man, a plan, a canal: Panama"
要求:忽略符号,只保留英文字符串和数字, 使得保留下的字符串正序,到序均为同一个字符串;
将空字符串定义为有效的回文串; 如果是回文串返回True, 否返回False
"""
python 切片:
[-1] [:-1] [::-1] [n::-1]都是python中切片的使用方法;
[-1]:获取最后一个元素,类似于matlab中的end;
[:-1]:除了最后一个元素,获取其他所有的元素;
[::-1]:对第一个到最后一个元素进行倒序之后取出;
[n::-1]:对第一个到第n个元素进行倒序后取出。
"""
"""
正则表达式[\w]+,\w+,[\w+] 三者有何区别:
[\w]+和\w+没有区别,都是匹配数字和字母下划线的多个字符;
[\w+]表示匹配数字、字母、下划线和加号本身字符;
[\w_+]表示匹配数字、字母、下划线和加号本身字符;
"""
def isPalindrome(s):
s_sub = str.lower(re.sub('[\W_+]','',s))
s_rev = s_sub[::-1]
if s_sub == s_rev:
return True
else:
return False
def isPalindrome(s):
# isalpha()检测是否只有数字, isdigit()检测是否只有数字
s = s.lower()
c = "".join([x for x in s if x.isalpha() or x.isdigit()])
k = "".join([c[i] for i in range(len(c)-1, -1, -1)])
return c==k
思路:
1. 利用正则表达式 获取字符串中的数字和英文字符
2. 将字符串转换成小写, 然后利用python 的切片倒序
3. 最后判断比较
2. 字符串转换为整数
实现一个 myAtoi(string s) 函数,使其能将字符串转换成一个 32 位有符号整数
函数 myAtoi(string s) 的算法如下:
1. 读入字符串并丢弃无用的前导空格
2. 检查下一个字符(假设还未到字符末尾)为正还是负号,读取该字符(如果有)。 确定最终结 果是负数还是正数。 如果两者都不存在,则假定结果为正。
3. 读入下一个字符,直到到达下一个非数字字符或到达输入的结尾。字符串的其余部分将被忽略。
将前面步骤读入的这些数字转换为整数(即,"123" -> 123, "0032" -> 32)。如果没有读入数 字,则整数为 0 。必要时更改符号(从步骤 2 开始)。
4. 如果整数数超过 32 位有符号整数范围 [−2**31, 2**31 − 1] ,需要截断这个整数,使其保持在 这 个范围内。具体来说,小于 −2**31 的整数应该被固定为 −2**31 ,大于 2**31 − 1 的整数应 该被固定为 2**31 − 1 。
5. 返回整数作为最终结果。
注意:本题中的空白字符只包括空格字符 ' ' ; 除前导空格或数字后的其余字符串外,请勿忽略任何其他字符。
正则解法:
"""
^:匹配字符串开头
[\+\-]:代表一个+字符或-字符
?:前面一个字符可有可无
\d:一个数字
+:前面一个字符的一个或多个
\D:一个非数字字符
*:前面一个字符的0个或多个
"""
# 字符串转换为整数
def myAtoi(s):
it_c = max(min(int(*re.findall('^[\+\-]?\d+', s.lstrip())), 2**31 - 1), -2**31)
return int(it_c)
def myAtoi(s):
INT_MAX = 2147483647
INT_MIN = -2147483648
ss = s.lstrip() #清除左边多余的空格
num_re = re.compile(r'^[\+\-]?\d+') #设置正则规则
num = num_re.findall(ss) #查找匹配的内容
num = int(*num) #由于返回的是个列表,解包并且转换成整数
print("num", num)
return max(min(num,INT_MAX),INT_MIN) #返回值
力扣 官方解法 自动机思路:
假设程序在每个时刻有一个状态 s,每次从序列中输入一个字符 c,并根据字符 c 转移到下一个状态 s'。这样,我们只需要建立一个覆盖所有情况的从 s 与 c 映射到 s' 的表格即可解决题目中的问题。
' | +/- | number | other | |
start | start | signed | in_number | end |
signed | end | end | in_number | end |
in_number | end | end | in_number | end |
end | end | end | end | end |
另外自动机也需要记录当前已经输入的数字,只要在 s'
为 in_number
时,更新我们输入的数字,即可最终得到输入的数字。
INT_MAX = 2 ** 31 - 1
INT_MIN = -2 ** 31
class Automaton:
def __init__(self):
self.state = 'start'
self.sign = 1
self.ans = 0
self.table = {
'start': ['start', 'signed', 'in_number', 'end'],
'signed': ['end', 'end', 'in_number', 'end'],
'in_number': ['end', 'end', 'in_number', 'end'],
'end': ['end', 'end', 'end', 'end'],
}
def get_col(self, c):
if c.isspace():
return 0
if c == '+' or c == '-':
return 1
if c.isdigit():
return 2
return 3
def get(self, c):
self.state = self.table[self.state][self.get_col(c)]
if self.state == 'in_number':
self.ans = self.ans * 10 + int(c)
self.ans = min(self.ans, INT_MAX) if self.sign == 1 else min(self.ans, -INT_MIN)
elif self.state == 'signed':
self.sign = 1 if c == '+' else -1
class Solution:
def myAtoi(self, str: str) -> int:
automaton = Automaton()
for c in str:
automaton.get(c)
return automaton.sign * automaton.ans
复杂度分析:
时间复杂度:O(n),其中 n 为字符串的长度。我们只需要依次处理所有的字符,处理每个字符需要的时间为 O(1);
空间复杂度:O(1)。自动机的状态只需要常数空间存储
3. 子字符串
给定两个字符串 haystack 和 needle ,在 haystack 字符串中找出 needle 字符串出现的第一个位置(下标从 0 开始); 如果不存在,则返回 -1; 当 needle
是空字符串时,应当返回 0
def strStr(haystack, needle):
if needle in haystack and needle != "":
return haystack.index(needle)
elif needle == "":
return 0
else:
return -1
4. 外观数列
给定一个正整数 n ,输出外观数列的第 n 项;「外观数列」是一个整数序列,从数字 1 开始,序列中的每一项都是对前一项的描述。
递归公式定义的数字字符串序列:
countAndSay(1) = "1",countAndSay(n) 是对 countAndSay(n-1) 的描述,然后转换成另一个数字字符串
例:
1. 1
2. 11
3. 21
4. 1211
5. 111221
第一项是数字 1
描述前一项,这个数是 1 即 “ 一 个 1 ”,记作 "11"
描述前一项,这个数是 11 即 “ 二 个 1 ” ,记作 "21"
描述前一项,这个数是 21 即 “ 一 个 2 + 一 个 1 ” ,记作 "1211"
描述前一项,这个数是 1211 即 “ 一 个 1 + 一 个 2 + 二 个 1 ” ,记作 "111221"
"""
1. 当递归出口 n=1时 为1
2. 对上一个(n-1)结果进行遍历获取值
3. 设定计数器,计算同一个数字出现的次数
4. 如果数字相同,计数器加一
5. 若当前不满足,则将上次的值记录下,并重置计数器,重置需要判断是否重复的字符
6. 将最后的结果也追加到字符串上
"""
def is_c(n):
start, end = 0, 0
if n== 1:
return '1'
s = is_c(n-1)
ans = '' # 计数器
start, end = 0, 0
while end < len(s):
while end < len(s) and s[start] == s[end]: # 3
end += 1 # 4
ans += str(end - start) + s[start] # 5
start = end
return ans
5. 最长公共前缀
查找字符串数组中的最长公共前缀,若不存在公共前缀,返回空字符串 ""
输入:strs = ["flower","flow","flight"] 输出:"fl"
"""
先取第一个字符串当做他们的公共前缀
然后找出他和第2个字符串的公共前缀,然后再用这个找出的公共前缀分别和第3个,第4个……取最长的公共前缀
"""
def commonPrefix(strs):
if len(strs)==0:
return ''
pre = strs[0] # 第一个字符串
strs = strs[1:] # 第一个之后的字符串
for i in range(len(strs)):
count = 0
# 比较第一个字符串和 之后字符串的长度, 取长度最小的length
if len(pre) < len(strs[i]):
length = len(pre)
else:
length = len(strs[i])
for j in range(length):
if strs[i][j] == pre[j]: # 比较字符串对于位置是否相等
count += 1
else:
break
# 截取
pre = pre[:count]
return pre
"""
zip()是python 的内建函数,zip()函数接受一系列可迭代对象作为参数,
将不同对象中相对应的元素打包成一个元组(tuple),返回由这些元组组成的list列表,
如果传入的参数的长度不等,则返回的list列表的长度和传入参数中最短对象的长度相同
例1:
a =[1, 4, 5, 7]
b =[9, 5, 6, 8]
result = list(zip(a, b, c))
result: [(1, 9, 3), (4, 5, 5), (5, 6, 2), (7, 8, 7)]
例2:
res = ['flower', 'flow', 'filter']
for i in zip(*res):
print(i, set(i))
('f', 'f', 'f') {'f'}
('l', 'l', 'i') {'l', 'i'}
('o', 'o', 'l') {'l', 'o'}
('w', 'w', 't') {'w', 't'}
"""
def commonPrefix(strs):
result = ''
for i in zip(*strs):
if len(set(temp)) ==1:
result += temp[0]
else:
break
return result