力扣每日一题 6/19 排序+动态规划

简介: 力扣每日一题 6/19 排序+动态规划

2713.矩阵中严格递增的单元格数【困难

题目:

给你一个下标从 1 开始、大小为 m x n 的整数矩阵 mat,你可以选择任一单元格作为 起始单元格

从起始单元格出发,你可以移动到 同一行或同一列 中的任何其他单元格,但前提是目标单元格的值 严格大于 当前单元格的值。

你可以多次重复这一过程,从一个单元格移动到另一个单元格,直到无法再进行任何移动。

请你找出从某个单元开始访问矩阵所能访问的 单元格的最大数量

返回一个表示可访问单元格最大数量的整数。

示例 1:

输入:mat = [[3,1],[3,4]]

输出:2

解释:上图展示了从第 1 行、第 2 列的单元格开始,可以访问 2 个单元格。可以证明,无论从哪个单元格开始,最多只能访问 2 个单元格,因此答案是 2 。

示例 2:

输入:mat = [[1,1],[1,1]]

输出:1

解释:由于目标单元格必须严格大于当前单元格,在本示例中只能访问 1 个单元格。

示例 3:

输入:mat = [[3,1,6],[-9,5,7]]

输出:4

解释:上图展示了从第 2 行、第 1 列的单元格开始,可以访问 4 个单元格。可以证明,无论从哪个单元格开始,最多只能访问 4 个单元格,因此答案是 4 。



分析问题:

      这道题旨在寻找一个最大解,可以用动态规划来解,而题意又是让我们顺序移动单元格,只能从小到大的顺序,因此我们可以用一个哈希表来记录每个值所对应的坐标,遍历每个可能的起点。

       在这个过程中,我们可以维护两个数组 rowMax 和 colMax,分别记录每一行和每一列的最大递增长度。初始时,这两个数组的所有元素都为 0。

       对于每个值对应的所有单元格位置,我们按照位置顺序遍历,对于每个位置 (i,j),我们可以计算出以该位置为终点的最大递增长度为 1+max(rowMax[i],colMax[j]),更新答案,然后更新 rowMax[i]colMax[j]

代码实现:

class Solution:
    def maxIncreasingCells(self, mat: List[List[int]]) -> int:
        M = len(mat)
        N = len(mat[0])
 
        # 建立一个哈希表
        value_buckets = defaultdict(list)
        
        for i in range(M):
            for j in range(N):
                value_buckets[mat[i][j]].append((i, j))
 
        row_best = [0] * M
        col_best = [0] * N
        ans = 0
 
        for val in sorted(value_buckets.keys()):
            cells = value_buckets[val]
            updates = []
            
            for r, c in cells:
                mx = 1 + max(row_best[r], col_best[c])
                updates.append((r, c, mx))
                ans = max(ans, mx)
            
            for r, c, mx in updates:
                row_best[r] = max(row_best[r], mx)
                col_best[c] = max(col_best[c], mx)
        
        return ans


 

总结:

代码详解:

       首先,通过 len(mat)len(mat[0]) 分别获取了输入矩阵 mat 的行数 M 和列数 N

       然后,创建了一个默认字典 value_buckets 。在接下来的两层循环中,遍历矩阵 mat 的每个元素。对于每个元素的值,将其对应的坐标 (i, j) 添加到 value_buckets 中以该值为键的列表中。

       接着,创建了两个列表 row_bestcol_best ,分别用于记录每行和每列的最佳值,并初始化为全 0 。还初始化了一个变量 ans 用于保存最终的结果,并初始化为 0 。

       之后,对 value_buckets 中的键(即矩阵中的值)进行排序。对于每个排序后的键值 val ,获取对应的坐标列表 cells 。然后创建一个空列表 updates 用于保存后续的更新信息。

       在遍历 cells 中的每个坐标 (r, c) 时,计算当前位置能达到的最大值 mx ,它等于 1 加上 row_best[r]col_best[c] 中的最大值。将 (r, c, mx) 添加到 updates 列表中,并更新 ansansmx 中的最大值。

       最后,再次遍历 updates 列表,更新 row_best[r]col_best[c] 为它们自身和 mx 中的最大值。

       最终,方法返回 ans ,即矩阵中按照特定规则能达到的最大结果值。


主要考查内容

  1. 对二维列表的遍历和操作。
  2. 使用默认字典 defaultdict 来根据值存储坐标。
  3. 对值进行排序,并基于排序后的结果进行一系列计算和更新操作。
  4. 维护两个分别记录每行和每列最佳值的列表 row_bestcol_best

通过这段代码可以学到

  1. 如何有效地处理二维数组中的数据。
  • 例如通过两层循环遍历二维数组的每个元素。
  1. 运用 defaultdict 来根据特定的值组织数据。
  • 方便后续按照值的顺序进行处理。
  1. 结合排序和逐步更新的策略来解决复杂的最值问题。
  • 通过比较和更新 row_bestcol_best 来获取最终的最大结果。

“千金纵买相如赋,脉脉此情谁诉。”——《摸鱼儿·更能消几番风雨》

目录
相关文章
|
1月前
【LeetCode-每日一题】 删除排序数组中的重复项
【LeetCode-每日一题】 删除排序数组中的重复项
20 4
|
3月前
|
存储 算法
LeetCode第83题删除排序链表中的重复元素
文章介绍了LeetCode第83题"删除排序链表中的重复元素"的解法,使用双指针技术在原链表上原地删除重复元素,提供了一种时间和空间效率都较高的解决方案。
LeetCode第83题删除排序链表中的重复元素
|
3月前
|
算法 索引
LeetCode第34题在排序数组中查找元素的第一个和最后一个位置
这篇文章介绍了LeetCode第34题"在排序数组中查找元素的第一个和最后一个位置"的解题方法,通过使用双指针法从数组两端向中间同时查找目标值,有效地找到了目标值的首次和最后一次出现的索引位置。
LeetCode第34题在排序数组中查找元素的第一个和最后一个位置
|
3月前
|
存储 算法 Java
LeetCode初级算法题:反转链表+统计N以内的素数+删除排序数组中的重复项Java详解
LeetCode初级算法题:反转链表+统计N以内的素数+删除排序数组中的重复项Java详解
45 0
|
3月前
|
算法 索引 Python
【Leetcode刷题Python】34. 在排序数组中查找元素的第一个和最后一个位置(二分查找)
解决LeetCode "在排序数组中查找元素的第一个和最后一个位置" 问题的方法。第一种方法是使用两次二分查找,首先找到目标值的最左边界,然后找到最右边界。第二种方法是利用Python的list.index()方法,先正序找到起始位置,再逆序找到结束位置,并给出了两种方法的Python实现代码。
62 0
|
5月前
力扣随机一题 哈希表 排序 数组
力扣随机一题 哈希表 排序 数组
33 1
|
5月前
|
缓存
力扣每日一题 6/14 动态规划+数组
力扣每日一题 6/14 动态规划+数组
40 1
|
5月前
|
算法
【经典LeetCode算法题目专栏分类】【第10期】排序问题、股票问题与TOP K问题:翻转对、买卖股票最佳时机、数组中第K个最大/最小元素
【经典LeetCode算法题目专栏分类】【第10期】排序问题、股票问题与TOP K问题:翻转对、买卖股票最佳时机、数组中第K个最大/最小元素
|
5月前
|
算法 索引
力扣每日一题 6/28 动态规划/数组
力扣每日一题 6/28 动态规划/数组
52 0
|
5月前
|
算法
力扣每日一题 6/16 字符串 + 随机一题 动态规划/数学
力扣每日一题 6/16 字符串 + 随机一题 动态规划/数学
45 0