28.实现strStr()
KMP算法
当出现字符串不匹配时,可以记录一部分之前已经匹配的文本内容,利用这些信息避免从头再去做匹配。
class Solution:
# 获取next数组
def get_next(self, T):
i = 0 #指向主串的指针
j = -1 #指向模式串的指针,一开始
next_val = [-1] * len(T) #要返回的next数组
while i < len(T)-1:
if j == -1 or T[i] == T[j]: #匹配成功,相同前缀长度+1.找不时直接开始下一位
i += 1
j += 1
# next_val[i] = j
if i < len(T) and T[i] != T[j]:
next_val[i] = j
else: #如果字符成功则跳过
next_val[i] = next_val[j]
else: #匹配不成功则在前面的子串中继续搜索,直到找不到
j = next_val[j]
return next_val
# KMP算法
def kmp(self, S, T):
i = 0 #主串的指针
j = 0 #模版的指针
next_val = self.get_next(T)
while i < len(S) and j < len(T):
if j == -1 or S[i] == T[j]: #S[i]==T[j]表示匹配成功,j==-1表示找不到下一个点,从S[i+1]开始和T[0]重新匹配
i += 1
j += 1
else:
j = next_val[j] #匹配不到时用next找下一个比较起点
if j == len(T): #while循环结束后,要么是找到合适匹配,要么是遍历完主串都没有找到合适匹配
return i - j
else:
return -1
if __name__ == '__main__':
haystack = 'acabaabaabcacaabc'
needle = 'abaabcac'
s = Solution()
print(s.kmp(haystack, needle)) # 输出 "5"
RK算法
BM算法
459.重复的子字符串
双指针法
class Solution:
def repeatedSubstringPattern(self, s: str) -> bool:
n = len(s)
for m in range(1,n//2+1):
if n % m == 0:
match = True
for j in range(m,n):
if s[j] != s[j-m]:
match = False
break
if match:
return True
return False
旋转数组
344.反转字符串
对撞指针
class Solution:
def reverseString(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
"""
l = 0
r = len(s)-1
while l < r:
s[l],s[r] = s[r],s[l]
l += 1
r -= 1
346.反转字符串中的元音字母
对撞指针
注意:
字符串是不可变的对象,需要将其转换成列表的形式。
s = list(s)
返回时要将列表转换为字符串
‘’.join(s)
''中的符号为转换后的间隔
class Solution:
def reverseVowels(self, s: str) -> str:
yuanyin = ['a','e','i','o','u']
left = 0
right = len(s)-1
s = list(s)
while left<right:
while left<right and s[left].lower() not in yuanyin:
left += 1
while left<right and s[right].lower() not in yuanyin:
right -= 1
s[left],s[right] = s[right],s[left]
left += 1
right -= 1
return ''.join(s)
119.删去字符串中的元音
def removeVowels(s):
vowels = ['a','e','i','o','u']
res = ''
for c in s:
if c.lower() not in vowels:
res += c
return res
541.反转字符串二
start+2k
对于特殊情况1:对right执行left+k-1,如果超出字符串了,则取len(s)-1
对于特殊情况2:如果start超过了len(s)就不会执行,对剩余的left~right执行
class Solution:
def reverseStr(self, s: str, k: int) -> str:
s = list(s)
for start in range(0,len(s),2*k):
left = start
right = min(left+k-1,len(s)-1)
while left<right:
s[left],s[right] = s[right],s[left]
left += 1
right -= 1
return ''.join(s)
557.反转字符串中的单词三
class Solution:
def reverseWords(self, s: str) -> str:
s = list(s)
n = len(s)
left = 0
def reverseWord(s,left,right):
while left<right:
s[left],s[right] = s[right],s[left]
left += 1
right -= 1
while left<n:
if s[left] != ' ':
right = left
while right+1 < n and s[right+1] != ' ':
right += 1
reverseWord(s,left,right)
left = right+1
else:
left += 1
return ''.join(s)
58.最后一个单词的长度
方法一:从左往右遍历
class Solution:
def lengthOfLastWord(self, s: str) -> int:
s = list(s)
start = 0
end = 0
while end < len(s):
while start < len(s) and s[start] == ' ':
start += 1
end = start
while end < len(s) and s[end] != ' ':
end += 1
len_ = end - start
start = end
return len_
方法二:从右往左遍历
和上述方法有三点不同
(1)end和start是从后往前记起的
(2)end充当之前start的位置,start充当之前end的位置
(3)一次遍历即可return
class Solution:
def lengthOfLastWord(self, s: str) -> int:
s = list(s)
start = len(s)-1
end = len(s)-1
while end >= 0:
while end >= 0 and s[end] == ' ':
end -= 1
start = end
while start >= 0 and s[start] != ' ':
start -= 1
len_ = end - start
return len_
leetcode8.字符串转换整数(atoi)
注意各种情况
class Solution:
def myAtoi(self, s: str) -> int:
s = list(s)
sign = 1
num = 0
i = 0
min_ = -2**31
max_ = 2**31-1
while i<len(s) and s[i] == ' ':
i += 1
if i<len(s)and (s[i] == '+' or s[i] == '-'):
if s[i] == '+':sign = 1
else: sign = -1
i += 1
while i < len(s) and (ord(s[i])-ord('0'))>=0 and (ord(s[i])-ord('0'))<=9:
num = num*10 + (ord(s[i])-ord('0'))
i+=1
if num*sign > max_:
return max_
elif num*sign < min_:
return min_
else:
return num*sign
165.比较版本号
注意把字符串转换为数字的方法:
while i1<len(version1) and version1[i1] != '.':
v1 = v1*10+(ord(version1[i1])-ord('0'))
i1 += 1
class Solution:
def compareVersion(self, version1: str, version2: str) -> int:
i1 = 0
i2 = 0
while i1 < len(version1) or i2 < len(version2):
v1 = 0
v2 = 0
while i1<len(version1) and version1[i1] != '.':
v1 = v1*10+(ord(version1[i1])-ord('0'))
i1 += 1
while i2<len(version2) and version2[i2] != '.':
v2 = v2*10+(ord(version2[i2])-ord('0'))
i2 += 1
if v1 != v2:
if v1>v2:
return 1
else:
return -1
i1+=1
i2+=1
return 0
12.整数转罗马数字
以上包含六种特殊情况,以及七种固定位置。共十三种情况。
按照从大到小的顺序遍历,寻找比他小的最近一个数字。
class Solution:
def intToRoman(self, num: int) -> str:
nums = [1000,900,500,400,100,90,50,40,10,9,5,4,1]
romans = ["M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"]
res = []
index = 0
while index<13:
while nums[index] <= num:
res.append(romans[index])
num -= nums[index]
index += 1
return "".join(res)
13.罗马数字转整数
应用了字典
class Solution:
def romanToInt(self, s: str) -> int:
table = {"I":1,"V":5,"X":10,"L":50,"C":100,"D":500,"M":1000}
sum = 0
pre = table[s[0]]
for i in range(1,len(s)):
curr = table[s[i]]
if pre < curr:
sum -= pre
else:
sum += pre
pre = curr
sum += pre
return sum
38.外观数列
def countAndSay(n):
curr = "1"
for i in range(1,n):
prev = curr
curr = ""
now = prev[0]
count = 1
for j in range(1, len(prev)):
if prev[j] == now:
count += 1
else:
curr = curr + str(count)
curr = curr + now
now = prev[j]
count = 1
curr = curr + str(count)
curr = curr + now
return curr
6.Z字形变换
方法一:
class Solution:
def convert(self, s: str, numRows: int) -> str:
n = len(s)
i = 0
sbs = [''for _ in range(numRows)]
while i<n :
idx = 0
for idx in range(numRows) :
if i >= n:
break
sbs[idx]= sbs[idx]+s[i]
i += 1
idx = 0
for idx in range(numRows-2,0,-1):
if i >= n:
break
sbs[idx]= sbs[idx]+s[i]
i += 1
res = []
for j in range(numRows):
res.append(sbs[j])
return "".join(res)
方法二:
用goingdown表示走向是向下还是向上。
当numRows的值为1时,向下或向上都会超过索引,所以没有操作。
class Solution:
def convert(self, s: str, numRows: int) -> str:
n = len(s)
i = 0
goingdown = False
currRow = 0
sbs = [''for _ in range(numRows)]
for i in range(n):
sbs[currRow]= sbs[currRow]+s[i]
if currRow == numRows-1 or currRow == 0:
goingdown = not goingdown
if numRows > 1:
if goingdown:
currRow += 1
else:
currRow -= 1
res = []
for j in range(numRows):
res.append(sbs[j])
return "".join(res)
按字符索引找规律
(找规律的方法不太喜欢,这里就没有写)