还是贪心,今天浅试一下困难程度的,一题中等,一题困难
给你一个整数数组 nums
,判断这个数组中是否存在长度为 3
的递增子序列。
如果存在这样的三元组下标 (i, j, k)
且满足 i < j < k
,使得 nums[i] < nums[j] < nums[k]
,返回 true
;否则,返回 false
。
示例 1:
输入:nums = [1,2,3,4,5] 输出:true 解释:任何 i < j < k 的三元组都满足题意
示例 2:
输入:nums = [5,4,3,2,1] 输出:false 解释:不存在满足题意的三元组
class Solution:
def increasingTriplet(self, nums: List[int]) -> bool:
one = two = float('inf')
for three in nums:
if three > two: return True
elif three <= one: one = three
else: two = three
return False
给你一个输入字符串 (s
) 和一个字符模式 (p
) ,请你实现一个支持 '?'
和 '*'
匹配规则的通配符匹配:
'?'
可以匹配任何单个字符。'*'
可以匹配任意字符序列(包括空字符序列)。
判定匹配成功的充要条件是:字符模式必须能够 完全匹配 输入字符串(而不是部分匹配)。
示例 1:
输入:s = "aa", p = "a" 输出:false 解释:"a" 无法匹配 "aa" 整个字符串。
示例 2:
输入:s = "aa", p = "*" 输出:true 解释:'*' 可以匹配任意字符串。
示例 3:
输入:s = "cb", p = "?a" 输出:false 解释:'?' 可以匹配 'c', 但第二个 'a' 无法匹配 'b'。
但是*也可以和a~z之间的小写字母随意排列
这题贪心对我太难了,还是看官方题解吧
我们以 p=∗ abcd ∗为例,p 可以匹配所有包含子串 abcd 的字符串,也就是说,我们只需要暴力地枚举字符串 s 中的每个位置作为起始位置,并判断对应的子串是否为 abcd即可。这种暴力方法的时间复杂度为 O(mn)O(mn)O(mn),与动态规划一致,但不需要额外的空间。
如果 p=∗ abcd∗efgh∗i ∗ 呢?显然,p可以匹配所有依次出现子串 abcd、efgh、i 的字符串。此时,对于任意一个字符串 s,我们首先暴力找到最早出现的 abcd,随后从下一个位置开始暴力找到最早出现的 efgh,最后找出 i,就可以判断 s 是否可以与 p匹配。这样「贪心地」找到最早出现的子串是比较直观的,因为如果 s 中多次出现了某个子串,那么我们选择最早出现的位置,可以使得后续子串能被找到的机会更大。
因此,如果模式 p的形式为 ∗ u1∗u2∗u3 ∗⋯∗ux ∗即字符串(可以为空)和星号交替出现,并且首尾字符均为星号,那么我们就可以设计出下面这个基于贪心的暴力匹配算法。算法的本质是:如果在字符串 s 中首先找到 u 1 ,再找到 u2,u3,⋯ ,ux ,那么 s 就可以与模式 p 匹配,伪代码如下:
// 我们用 sIndex 和 pIndex 表示当前遍历到 s 和 p 的位置
// 此时我们正在 s 中寻找某个 u_i
// 其在 s 和 p 中的起始位置为 sRecord 和 pRecord
// sIndex 和 sRecord 的初始值为 0
// 即我们从字符串 s 的首位开始匹配
sIndex = sRecord = 0
// pIndex 和 pRecord 的初始值为 1
// 这是因为模式 p 的首位是星号,那么 u_1 的起始位置为 1
pIndex = pRecord = 1
while sIndex < s.length and pIndex < p.length do
if p[pIndex] == '*' then
// 如果遇到星号,说明找到了 u_i,开始寻找 u_i+1
pIndex += 1
// 记录下起始位置
sRecord = sIndex
pRecord = pIndex
else if match(s[sIndex], p[pIndex]) then
// 如果两个字符可以匹配,就继续寻找 u_i 的下一个字符
sIndex += 1
pIndex += 1
else if sRecord + 1 < s.length then
// 如果两个字符不匹配,那么需要重新寻找 u_i
// 枚举下一个 s 中的起始位置
sRecord += 1
sIndex = sRecord
pIndex = pRecord
else
// 如果不匹配并且下一个起始位置不存在,那么匹配失败
return False
end if
end while
// 由于 p 的最后一个字符是星号,那么 s 未匹配完,那么没有关系
// 但如果 p 没有匹配完,那么 p 剩余的字符必须都是星号
return all(p[pIndex] ~ p[p.length - 1] == '*')
作者:力扣官方题解
链接:https://leetcode.cn/problems/wildcard-matching/solutions/315802/tong-pei-fu-pi-pei-by-leetcode-solution/
然而模式 p并不一定是 ∗ u1∗u2∗u3 ∗⋯∗ux ∗的形式:
模式 p的开头字符不是星号;
模式 p的结尾字符不是星号。
第二种情况处理起来并不复杂。如果模式 p的结尾字符不是星号,那么就必须与字符串 s 的结尾字符匹配。那么我们不断地匹配 s 和 p 的结尾字符,直到 p 为空或者 p 的结尾字符是星号为止。在这个过程中,如果匹配失败,或者最后 p 为空但 s 不为空,那么需要返回 False
第一种情况的处理也很类似,我们可以不断地匹配 s 和 p 的开头字符。下面的代码中给出了另一种处理方法,即修改 sRecord和 tRecord 的初始值为 −1,表示模式 p 的开头字符不是星号,并且在匹配失败时进行判断,如果它们的值仍然为 −1,说明没有「反悔」重新进行匹配的机会。
class Solution:
def isMatch(self, s: str, p: str) -> bool:
def allStars(st: str, left: int, right: int) -> bool:
return all(st[i] == '*' for i in range(left, right))
def charMatch(u: str, v: str) -> bool:
return u == v or v == '?'
sRight, pRight = len(s), len(p)
while sRight > 0 and pRight > 0 and p[pRight - 1] != '*':
if charMatch(s[sRight - 1], p[pRight - 1]):
sRight -= 1
pRight -= 1
else:
return False
if pRight == 0:
return sRight == 0
sIndex, pIndex = 0, 0
sRecord, pRecord = -1, -1
while sIndex < sRight and pIndex < pRight:
if p[pIndex] == '*':
pIndex += 1
sRecord, pRecord = sIndex, pIndex
elif charMatch(s[sIndex], p[pIndex]):
sIndex += 1
pIndex += 1
elif sRecord != -1 and sRecord + 1 < sRight:
sRecord += 1
sIndex, pIndex = sRecord, pRecord
else:
return False
return allStars(p, pIndex, pRight)
作者:力扣官方题解
链接:https://leetcode.cn/problems/wildcard-matching/solutions/315802/tong-pei-fu-pi-pei-by-leetcode-solution/
我还是没有很懂贪心这种东西,真的,我真的可能......脑子有点不太方便吧,总之遇到编程算法就不太够用