[参考讲解]:灵茶山艾府大佬
LeetCode 6148. 矩阵中的局部最大值
https://leetcode.cn/problems/largest-local-values-in-a-matrix/
模拟
使用 pop()
节省内存:
class Solution:
def largestLocal(self, grid: List[List[int]]) -> List[List[int]]:
n = len(grid)
for i in range(n - 2):
for j in range(n - 2):
grid[i][j] = max(max(row[j:j + 3]) for row in grid[i:i + 3])
grid[i].pop()
grid[i].pop()
grid.pop()
grid.pop()
return grid
LeetCode 6150. 根据模式串构造最小数字
https://leetcode.cn/problems/construct-smallest-number-from-di-string/
暴力全排列
时间复杂度:
O
(
n
∗
n
!
)
O(n*n!)
O(n∗n!)。
permutations()
函数可以求出所需要数字的全排列,然后枚举看是否满足条件。
from itertools import permutations
class Solution:
def smallestNumber(self, pattern: str) -> str:
n = len(pattern)
ans = []
for lst in permutations(range(1, 2 + n)):
for i in range(n):
if lst[i] < lst[i+1] and pattern[i] == 'D':
break
if lst[i] > lst[i+1] and pattern[i] == 'U':
break
else:
return ''.join([str(x) for x in lst])
贪心栈
时间复杂度:
O
(
n
)
O(n)
O(n)。
看到 D
则入栈,看到 I
出栈,最后结束的时候若栈不空,将栈中元素依次弹出。
class Solution:
def smallestNumber(self, pattern: str) -> str:
i = 1
ans = ''
stack = []
for c in pattern:
# 遇到 D 入栈
if c == 'D':
stack.append(str(i))
# 遇到 I 出栈
else:
ans += str(i)
while stack:
ans += stack.pop()
i += 1
# 最后的结果比 len(pattern) 多 1 个
ans += str(i)
# 若最后栈不空,依次弹出
while stack:
ans += stack.pop()
return ans
LeetCode 6151. 统计特殊整数
https://leetcode.cn/problems/count-special-integers/
数学模拟
class Solution:
def countSpecialNumbers(self, n: int) -> int:
# 计算 9 * 8 * 7 * ...
def countPermutation(cnt: int):
a = [1,]
s = 1
for i in range(11 - cnt, 10):
s *= i
a.append(s)
a.reverse()
return a
# 计算每个位数所能得到的最大组合数
def countMax(cnt: int):
a = [9,]
s = 9
for i in range(9, 9 - cnt + 1, -1):
s *= i
a.append(s)
return a
nums = [int(c) for c in list(str(n))] # 原数字转为数组
numsLength = len(nums) # 数组长度
visited = set() # 标记 0~9 是否被使用
table = countPermutation(numsLength) # 记录对应位置的数字确定后能得到的最多符合条件的组合数
ans = 0
# 假设 n 的位数 numsLength, 先把 numsLength - 1 位数的所有情况加起来
table2 = countMax(numsLength - 1)
if numsLength - 1 > 0:
ans += sum(table2[:numsLength - 1])
# 再计算 numsLength 位数的情况
for i in range(numsLength):
x = nums[i]
# 0 ~ x-1 是否已经被使用
for k in range(x):
if k in visited:
x -= 1
# 如果是首个数字排除 0 的可能性
if i == 0:
x -= 1
ans += table[i] * x # 数字确定后能得到的最多符合条件的组合数
# 遍历到最后一位,只需要判断是否为符合条件即可
if i == numsLength - 1 and nums[-1] not in visited:
ans += 1
if nums[i] not in visited:
visited.add(nums[i])
else:
break
return ans