链接: 2287. 重排字符形成目标字符串
给你两个下标从 0 开始的字符串 s 和 target 。你可以从 s 取出一些字符并将其重排,得到若干新的字符串。
从 s 中取出字符并重新排列,返回可以形成 target 的 最大 副本数。
定级Easy。
统计target中对应字符的数量在s中有几倍数。
class Solution:
class Solution:
def rearrangeCharacters(self, s: str, target: str) -> int:
d = collections.defaultdict(int)
for c in s:
d[c] += 1
ans = 1e9
d2 = collections.defaultdict(int)
for c in target:
d2[c] += 1
for c in target:
ans = min(ans, d.get(c,0)//d2.get(c,0) )
return ans
链接: 2288. 价格减免
句子 是由若干个单词组成的字符串,单词之间用单个空格分隔,其中每个单词可以包含数字、小写字母、和美元符号 ‘$’ 。如果单词的形式为美元符号后跟着一个非负实数,那么这个单词就表示一个价格。
例如 “$100”、“$23” 和 “ 6.75 " 表 示 价 格 , 而 " 100 " 、 " 6.75" 表示价格,而 "100"、" 6.75"表示价格,而"100"、"” 和 “2$3” 不是。
注意:本题输入中的价格均为整数。
给你一个字符串 sentence 和一个整数 discount 。对于每个表示价格的单词,都在价格的基础上减免 discount% ,并 更新 该单词到句子中。所有更新后的价格应该表示为一个 恰好保留小数点后两位 的数字。
返回表示修改后句子的字符串。
定级Medium。
模拟题,拆分后修改即可。
class Solution:
def discountPrices(self, sentence: str, discount: int) -> str:
words = sentence.split(' ')
ans = []
for word in words:
if word[0] == '$' and word[1:].isdigit() and float(word[1:]) >= 0:
price = float(word[1:])
ans.append(f'${price*0.01*(100-discount):.2f}')
continue
ans.append(word)
return ' '.join(ans)
链接: 2289. 使数组按非递减顺序排列
给你一个下标从 0 开始的整数数组 nums 。在一步操作中,移除所有满足 nums[i - 1] > nums[i] 的 nums[i] ,其中 0 < i < nums.length 。
重复执行步骤,直到 nums 变为 非递减 数组,返回所需执行的操作数。
这题定级Medium就离谱,直接被卡死。
思路是单调栈+dp,和一般单调栈应用不同之处在于:
留在栈内的部分
。出栈的数据
。class Solution:
def totalSteps(self, nums: List[int]) -> int:
"""
1.每个数只要前边有比它大的数,一定会被删除。
2.每个数都会被他前边更大的数删除,但不一定是最近那个,因为那个数可能会被自己前边的大数删掉
如[5,4,1,2], 2这个数不会被4删掉,因为4会被5删掉。
但这没关系,这相当于5代替了4的位置。
3.因此每个数被删除的时间只取决于它前边比它小的数能挡几轮:
4.换言之:每个数被删除的时间dp[i]=max{dp[j]+1|k
n = len(nums)
stack = []
dp=[0]*n
for i in range(n):
if i > 0 and nums[i] < nums[i-1]:
dp[i] = 1
while stack and nums[stack[-1]] <= nums[i]: # 构造单调递减栈,需要把栈顶比本数小的数都干掉
dp[i] = max(dp[i],dp[stack[-1]]+1)
stack.pop()
if not stack:
dp[i] = 0
stack.append(i)
return max(dp)
链接: 2290. 到达角落需要移除障碍物的最小数目
给你一个下标从 0 开始的二维整数数组 grid ,数组大小为 m x n 。每个单元格都是两个值之一:
0 表示一个 空 单元格,
1 表示一个可以移除的 障碍物 。
你可以向上、下、左、右移动,从一个空单元格移动到另一个空单元格。
现在你需要从左上角 (0, 0) 移动到右下角 (m - 1, n - 1) ,返回需要移除的障碍物的 最小 数目。
输入:grid = [[0,1,1],[1,1,0],[1,1,0]]
输出:2
解释:可以移除位于 (0, 1) 和 (0, 2) 的障碍物来创建从 (0, 0) 到 (2, 2) 的路径。
可以证明我们至少需要移除两个障碍物,所以返回 2 。
注意,可能存在其他方式来移除 2 个障碍物,创建出可行的路径。
示例 2:
输入:grid = [[0,1,0,0,0],[0,1,0,1,0],[0,0,0,1,0]]
输出:0
解释:不移除任何障碍物就能从 (0, 0) 到 (2, 4) ,所以返回 0 。
这题虽然定级Hard。
然而是就是最短路模板
参考 [LeetCode解题报告] 6081. 到达角落需要移除障碍物的最小数目
class PriorityQueue:
def __init__(self):
self._queue = []
self._index = 0 # 传入顺序
def push(self, item, priority):
heapq.heappush(self._queue, (priority, self._index, item))
self._index += 1
def pop(self):
return heapq.heappop(self._queue)[-1]
def __str__(self):
return str(self._queue)
def __len__(self):
return len(self._queue)
class Solution:
def minimumObstacles(self, grid: List[List[int]]) -> int:
m,n = len(grid),len(grid[0])
q = PriorityQueue()
q.push((0,0,0),0)
visited = {(0,0):0}
while q:
x,y,z =q.pop()
if x == m-1 and y == n -1:
return z
for x1,y1 in [(x-1,y),(x+1,y),(x,y-1),(x,y+1)]:
if not (0<=x1<m and 0<=y1<n):
continue
if (x1,y1) not in visited or visited[(x1,y1)] > z+grid[x1][y1]:
visited[(x1,y1)] = z+grid[x1][y1]
q.push((x1,y1,visited[(x1,y1)]),visited[(x1,y1)])
return -1