Z字形变换
题目描述:将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 “LEETCODEISHIRING” 行数为 3 时,排列如下:
L C I R
E T O E S I I G
E D H N
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“LCIRETOESIIGEDHN”。
思路分析
(1)创建一个二维矩阵,模拟Z字形读取字符串的过程,最后在按行遍历矩阵。
(2)我们发现遍历字符串s的时候对应字符在Z字形中行索引的变化是从0到n再从n到0,那么按照行索引的变化,将每个字符填入相应的行就行了。可以发现的是,行索引在行为0或者n时才会变化,其他地方不变。
思路1代码
class Solution:
def convert(self, s: str, numRows: int) -> str:
if not s:return ""
if numRows==1:return s
m = numRows
n = (len(s)//(1+m-2) + 1)*(1+m-2)
matrix = [[0]*n for _ in range(m)]
i, j = 0, 0
p = 1+m-2
for v in s:
if i<m-1 and j%p==0:
matrix[i][j]=v
i += 1
elif i==m-1 and j%p==0:
matrix[i][j]=v
i -= 1
j += 1
elif j%p !=0:
matrix[i][j]=v
i -= 1
j += 1
else:return
res = ""
for i in range(len(matrix)):
for j in range(len(matrix[0])):
if matrix[i][j]!=0:
res += matrix[i][j]
return res
思路2代码
class Solution:
def convert(self, s: str, numRows: int) -> str:
if numRows<2:return s
res = ["" for _ in range(numRows)]
i, flag = 0, -1 #falg用来表示行索引是增还是减
for v in s:
res[i] += v
if i==0 or i==numRows-1:flag = -flag
i += flag
return "".join(res)
模型匹配
题目描述:你有两个字符串,即pattern和value。 pattern字符串由字母"a"和"b"组成,用于描述字符串中的模式。例如,字符串"catcatgocatgo"匹配模式"aabab"(其中"cat"是"a",“go"是"b”),该字符串也匹配像"a"、"ab"和"b"这样的模式。但需注意"a"和"b"不能同时表示相同的字符串。编写一个方法判断value字符串是否匹配pattern字符串。
示例 1:
输入: pattern = “abba”, value = “dogcatcatdog”
输出: true
示例 2:
输入: pattern = “abba”, value = “dogcatcatfish”
输出: false
基本思路:(1)先统计pattern每个字母a,b的个数,如果能匹配成功那么 a字母的数量a字母匹配长度 + b字母的数量b字母匹配的长度 = value的长度。
(2)那么我们列举所有的字母a和字母b匹配的长度的可能的情况
(3)对于每一种情况,遍历patter遇到a,则取出value对应长度的字符串放入集合中,如果下一次又遇到a,匹配的字符串跟集合中不同,则说明匹配失败,否则继续,遍历到b也是一样
(4)最后判断字母a和字母b匹配的字符串是否相等。
class Solution:
def patternMatching(self, pattern: str, value: str) -> bool:
n_a, n_b = pattern.count("a"), pattern.count("b")
if n_a == 0 and n_b==0:
return not value
if n_a == 0:
return (len(value)%n_b==0) and n_b*value[:len(value)//n_b] == value
if n_b == 0:
return (len(value)%n_a==0) and n_a*value[:len(value)//n_a] == value
candidate = []
m = len(value)//n_a
for i in range(0, m+1):
if (len(value)-i*n_a)%n_b == 0:
candidate.append([i, (len(value)-i*n_a)//n_b])
for i,j in candidate:
if self.check(pattern, value, i, j):
return True
return False
def check(self, pattern, value, i, j):
set1 = set()
set2 = set()
for c in pattern:
if c == 'a':
if set1 and value[:i] not in set1:
return False
set1.add(value[:i])
value = value[i:]
elif c == 'b':
if set2 and value[:j] not in set2:
return False
set2.add(value[:j])
value = value[j:]
if set1 == set2: ## a,b对应模式相同返回False
return False
return True
至少有k个重复字符的最长子串
题目描述:找到给定字符串(由小写字符组成)中的最长子串 T , 要求 T 中的每一字符出现次数都不少于 k 。输出 T 的长度。
输入:
s = “aaabb”, k = 3
输出:
3
最长子串为 “aaa” ,其中 ‘a’ 重复了 3 次。
基本思路:字符串S中出现次数小于k次的一定不会出现在最长子串T中,那么就可以根据不会出现在字符串中的字符将字符串S分成几个部分,然后在每个部分重复上述过程,直到子串所有字符均满足要求,
代码如下:
class Solution:
def longestSubstring(self, s: str, k: int) -> int:
if len(s)<k:
return 0
min_char = min(set(s), key=s.count)
if s.count(min_char)>=k:
return len(s)
return max(self.longestSubstring(a,k) for a in s.split(min_char))
通配符匹配
给定一个字符串 (s) 和一个字符模式 § ,实现一个支持 ‘?’ 和 ‘*’ 的通配符匹配。
‘?’ 可以匹配任何单个字符。
‘*’ 可以匹配任意字符串(包括空字符串)。
s 可能为空,且只包含从 a-z 的小写字母。
p 可能为空,且只包含从 a-z 的小写字母,以及字符 ? 和 *
基本思路:动态规划
class Solution:
def isMatch(self, s: str, p: str) -> bool:
m, n = len(s), len(p)
dp = [[False]*(n+1) for _ in range(m+1)]
dp[0][0] = True
for j in range(1,n+1):
if p[j-1]=="*":
dp[0][j] = dp[0][j-1]
for i in range(1,m+1):
for j in range(1,n+1):
if s[i-1]==p[j-1] or p[j-1]=="?":
dp[i][j] = dp[i-1][j-1]
elif p[j-1]=="*":
dp[i][j] = dp[i-1][j] or dp[i][j-1]
return dp[-1][-1]