给你一个由 正整数 组成、大小为 m x n
的矩阵 grid
。你可以从矩阵中的任一单元格移动到另一个位于正下方或正右侧的任意单元格(不必相邻)。从值为 c1
的单元格移动到值为 c2
的单元格的得分为 c2 - c1
。
你可以从 任一 单元格开始,并且必须至少移动一次。
返回你能得到的 最大 总得分。
提示:
m == grid.length
n == grid[i].length
2 <= m, n <= 1000
4 <= m * n <= 105
1 <= grid[i][j] <= 105
题目解析与解题思路
题目要求:
给定一个 m x n
的矩阵 grid
,矩阵由正整数构成。可以从矩阵中的任意单元格出发,并且移动到正下方或正右侧的任意单元格(不必相邻)。从值为 c1
的单元格移动到值为 c2
的单元格的得分为 c2 - c1
。要求返回可以获得的最大总得分。
解题思路:
-
初始化最小值数组:
- 设一个数组
lst
用于记录从上到下扫描每列时遇到的最小值。初始化lst
中的所有元素为INT_MAX
。
- 设一个数组
-
遍历矩阵:
- 对于矩阵中的每个元素
grid[i][j]
,需要考虑两种可能:- 从当前列的上方某个单元格移动到当前单元格。
- 从当前行的左侧某个单元格移动到当前单元格。
- 更新
ans
为当前最大得分。对于每个元素grid[i][j]
,计算从左侧或上方移动到该元素的可能最大得分,并更新ans
。
- 对于矩阵中的每个元素
-
更新最小值:
- 更新
mi
(当前行中最小值)和lst[j]
(当前列中最小值)以便在下一次计算时使用。
- 更新
-
返回最大得分:
- 经过所有元素的计算后,返回
ans
即为可获得的最大得分。
- 经过所有元素的计算后,返回
int max(int a, int b) {
return a > b ? a : b; // 返回较大的数
}
int min(int a, int b) {
return a < b ? a : b; // 返回较小的数
}
int maxScore(int** grid, int gridSize, int* gridColSize) {
int ans = INT_MIN; // 用于存储最大得分
int *lst = (int *)calloc(*gridColSize, sizeof(int)); // 动态分配数组 lst,用于存储每列的最小值
for(int j = 0; j < *gridColSize; j++) lst[j] = INT_MAX; // 初始化 lst 中的每个元素为 INT_MAX
for(int i = 0; i < gridSize; i++) {
int mi = INT_MAX; // 用于存储当前行中已经遍历过的最小值
for(int j = 0; j < *gridColSize; j++) {
// 更新 ans 为当前的最大得分
ans = max(ans, max(grid[i][j] - mi, grid[i][j] - lst[j]));
// 更新当前行中最小值 mi
mi = min(mi, grid[i][j]);
// 更新 lst[j] 为当前列的最小值
lst[j] = min(lst[j], mi);
}
}
// 释放 lst 数组的内存
free(lst);
return ans; // 返回最大得分
}
代码逻辑与功能分析
-
max
和min
函数:max
函数用于返回两个数中较大的那个。min
函数用于返回两个数中较小的那个。
-
lst
数组:lst
是一个动态分配的数组,用于记录每列中最小值。初始化为INT_MAX
以确保最小值的更新。
-
主循环:
- 外层循环遍历每一行。
- 内层循环遍历每一列,计算从左侧或上方移动到当前单元格的最大得分,并更新
ans
。 - 每次内层循环结束后,更新当前行和列的最小值,便于下一个单元格的计算。
-
结果返回:
- 最终返回
ans
,即为从任意起始点开始,经过合法移动后能获得的最大总得分。
- 最终返回
题目来源:https://leetcode.cn/problems/maximum-difference-score-in-a-grid/