[LeetCode周赛复盘] 第 295 场周赛20220529

[LeetCode周赛复盘] 第 295 场周赛20220529

    • 一、本周周赛总结
    • 二、 [Easy] 2287. 重排字符形成目标字符串
      • 1. 题目描述
      • 2. 思路分析
      • 3. 代码实现
    • 三、[Medium] 2288. 价格减免
      • 1. 题目描述
      • 2. 思路分析
      • 3. 代码实现
    • 四、[Medium] 2289. 使数组按非递减顺序排列
      • 1. 题目描述
      • 2. 思路分析
      • 3. 代码实现
    • 五、[Hard] 2290. 到达角落需要移除障碍物的最小数目
      • 1. 题目描述
      • 2. 思路分析
      • 3. 代码实现
    • 六、参考链接

一、本周周赛总结

  • 补一下上周的周赛。
  • 比赛时只做了前两题,被第三题卡没了,最后剩五分钟才想起来看看最后一题。
  • 结果最后一题就是最短路模板题,真的会谢。

二、 [Easy] 2287. 重排字符形成目标字符串

链接: 2287. 重排字符形成目标字符串

1. 题目描述

给你两个下标从 0 开始的字符串 s 和 target 。你可以从 s 取出一些字符并将其重排,得到若干新的字符串。

从 s 中取出字符并重新排列,返回可以形成 target 的 最大 副本数。

2. 思路分析

定级Easy。
统计target中对应字符的数量在s中有几倍数。

3. 代码实现

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

三、[Medium] 2288. 价格减免

链接: 2288. 价格减免

1. 题目描述

句子 是由若干个单词组成的字符串,单词之间用单个空格分隔,其中每个单词可以包含数字、小写字母、和美元符号 ‘$’ 。如果单词的形式为美元符号后跟着一个非负实数,那么这个单词就表示一个价格。

例如 “$100”、“$23” 和 “ 6.75 " 表 示 价 格 , 而 " 100 " 、 " 6.75" 表示价格,而 "100"、" 6.75""100""” 和 “2$3” 不是。
注意:本题输入中的价格均为整数。

给你一个字符串 sentence 和一个整数 discount 。对于每个表示价格的单词,都在价格的基础上减免 discount% ,并 更新 该单词到句子中。所有更新后的价格应该表示为一个 恰好保留小数点后两位 的数字。

返回表示修改后句子的字符串。

2. 思路分析

定级Medium。
模拟题,拆分后修改即可。

3. 代码实现

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)

四、[Medium] 2289. 使数组按非递减顺序排列

链接: 2289. 使数组按非递减顺序排列

1. 题目描述

给你一个下标从 0 开始的整数数组 nums 。在一步操作中,移除所有满足 nums[i - 1] > nums[i] 的 nums[i] ,其中 0 < i < nums.length 。

重复执行步骤,直到 nums 变为 非递减 数组,返回所需执行的操作数。

2. 思路分析

这题定级Medium就离谱,直接被卡死。
思路是单调栈+dp,和一般单调栈应用不同之处在于:

  • 一般单调栈都处理留在栈内的部分
  • 这题处理出栈的数据
    参考[LeetCode解题报告] 2289. 使数组按非递减顺序排列

3. 代码实现

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)

五、[Hard] 2290. 到达角落需要移除障碍物的最小数目

链接: 2290. 到达角落需要移除障碍物的最小数目

1. 题目描述

给你一个下标从 0 开始的二维整数数组 grid ,数组大小为 m x n 。每个单元格都是两个值之一:

0 表示一个 空 单元格,
1 表示一个可以移除的 障碍物 。
你可以向上、下、左、右移动,从一个空单元格移动到另一个空单元格。

现在你需要从左上角 (0, 0) 移动到右下角 (m - 1, n - 1) ,返回需要移除的障碍物的 最小 数目。

示例 1:
[LeetCode周赛复盘] 第 295 场周赛20220529_第1张图片

输入:grid = [[0,1,1],[1,1,0],[1,1,0]]
输出:2
解释:可以移除位于 (0, 1) 和 (0, 2) 的障碍物来创建从 (0, 0) 到 (2, 2) 的路径。
可以证明我们至少需要移除两个障碍物,所以返回 2 。
注意,可能存在其他方式来移除 2 个障碍物,创建出可行的路径。
示例 2:
[LeetCode周赛复盘] 第 295 场周赛20220529_第2张图片

输入:grid = [[0,1,0,0,0],[0,1,0,1,0],[0,0,0,1,0]]
输出:0
解释:不移除任何障碍物就能从 (0, 0) 到 (2, 4) ,所以返回 0 。

2. 思路分析

这题虽然定级Hard
然而是就是最短路模板
参考 [LeetCode解题报告] 6081. 到达角落需要移除障碍物的最小数目

3. 代码实现

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

六、参考链接

  • [python刷题模板] 广度优先搜索BFS
  • [python刷题模板] 单调栈

你可能感兴趣的:(今天开刷leetcode,力扣周赛复盘,leetcode,算法)