leetcode contest 300
题目质量还不错,第三题经典的动态规划,第四题感觉过于简单了。
6108. 解密消息
题目
给你字符串 key
和 message
,分别表示一个加密密钥和一段加密消息。解密 message
的步骤如下:
使用 key
中 26
个英文小写字母第一次出现的顺序作为替换表中的字母 顺序 。
将替换表与普通英文字母表对齐,形成对照表。
按照对照表 替换 message
中的每个字母。
空格 ‘ ‘ 保持不变。
例如,key = "happy boy"
(实际的加密密钥会包含字母表中每个字母 至少一次),据此,可以得到部分对照表('h' -> 'a'、'a' -> 'b'、'p' -> 'c'、'y' -> 'd'、'b' -> 'e'、'o' -> 'f')
。
返回解密后的消息。
示例 1:
输入:key = "the quick brown fox jumps over the lazy dog", message = "vkbs bs t suepuv" |
示例 2:
输入:key = "eljuxhpwnyrdgtqkviszcfmabo", message = "zwx hnfx lqantp mnoeius ycgk vcnjrdb" |
提示:
26 <= key.length <= 2000
key
由小写英文字母及 ‘ ‘ 组成key
包含英文字母表中每个字符('a'
到'z'
)至少一次1 <= message.length <= 2000
message
由小写英文字母和 ‘ ‘ 组成
地址
https://leetcode.cn/contest/weekly-contest-300/problems/decode-the-message/
题意
直接遍历
思路
- 按照题意首先将
key
中的字典序隐射表,然后将message
中的每个字符映射回来即可。 - 复杂度分析:
- 时间复杂度:$O(n + m))$, 其中 $n$ 为字符串
key
的长度,m
为字符串message
的长度。 - 空间复杂度:$O(|\Sigma|)$,字符集的大小为 $26$。
代码
class Solution { |
6111. 螺旋矩阵 IV
题目
给你两个整数:m
和 n
,表示矩阵的维数。
另给你一个整数链表的头节点 head
。
请你生成一个大小为 m x n
的螺旋矩阵,矩阵包含链表中的所有整数。链表中的整数从矩阵 左上角 开始、顺时针 按 螺旋 顺序填充。如果还存在剩余的空格,则用 -1
填充。
返回生成的矩阵。
示例 1:
输入:m = 3, n = 5, head = [3,0,2,6,8,1,7,9,4,2,5,5,0] |
示例 2:
输入:m = 1, n = 4, head = [0,1,2] |
提示:
1 <= m, n <= 105
1 <= m * n <= 105
- 链表中节点数目在范围
[1, m * n]
内 0 <= Node.val <= 1000
地址
https://leetcode.cn/contest/weekly-contest-299/problems/count-number-of-ways-to-place-houses/
题意
矩阵层次遍历问题
思路
- 经典的矩阵按照层次遍历问题,可以参考「54. 螺旋矩阵」相关解法,我们将数组中的值依次按照矩阵的层次遍历,将链表中的每一项按照顺序填写进去即可。
- 复杂度分析:
- 时间复杂度:$O(m \times n)$,其中 $m,n$ 为矩阵的行数与列数。
- 空间复杂度:$O(1)$。
代码
class Solution { |
6109. 知道秘密的人数
题目
在第 1
天,有一个人发现了一个秘密。
给你一个整数 delay
,表示每个人会在发现秘密后的 delay
天之后,每天 给一个新的人 分享 秘密。同时给你一个整数 forget
,表示每个人在发现秘密 forget
天之后会 忘记 这个秘密。一个人 不能 在忘记秘密那一天及之后的日子里分享秘密。
给你一个整数 n
,请你返回在第 n
天结束时,知道秘密的人数。由于答案可能会很大,请你将结果对 109 + 7
取余 后返回。
示例 1:
输入:n = 6, delay = 2, forget = 4 |
示例 2:
输入:n = 4, delay = 1, forget = 3 |
提示:
2 <= n <= 1000
1 <= delay < forget <= n
地址
https://leetcode.cn/problems/number-of-people-aware-of-a-secret/
题意
动态规划
思路
- 这个题目的动态规划比较有意思的,还是稍微不好思考,有多种解法可以满足要求,有多种解法:
- 解法一: 设 $dp[i]$ 标识第 $i$ 天新增的人数,此时我们可以知道第 $i$ 天新增的数目为 $dp[i] = \sum_{j=i-forget+1}^{i-delay}dp[j]$,第 $i$ 天的总人数为 $\sum_{i=n-forget+1}^{n}dp[i]$。用前缀和的解法,可以优化到 $O(n)$ 的时间复杂度。
- 解法二: 设 $dp[i][j]$ 标识当前第 $i$ 天时已经知道消息时长为 $j$ 的人数。此时我们可以知道如下推理:
$$
dp[i][j] = dp[i-1][j-1] \
dp[i][0] = \sum_{k=delay}^{forget} dp[i][k]
$$
第 $i-1$ 天且发现秘密为 $j$ 天的为 $dp[i-1][j]$, 当经过一天之后,总共有 $dp[i-1][j]$ 个人发现秘密的时间变为 $j+1$ 天,此时 $dp[i][j+1] = dp[i-1][j$,同时新的传播且发现秘密的人数需要统计所有大于等 $delay$ 的天数即可,此时 $dp[i][0] = \sum_{j=delay-1}^{forget-2}dp[i-1][j]$。
- 复杂度分析:
- 时间复杂度:$O(n^2)$, $n$ 表示给定的天数,可以优化到 $O(n)$ 的时间复杂度。
- 空间复杂度:$O(n)$,$n$ 表示给定的天数。
代码
- 解法一:
class Solution {
public:
int peopleAwareOfSecret(int n, int delay, int forget) {
long long mod = 1e9 + 7;
long long ans = 0;
vector<long long> sum(n + 1);
vector<long long> dp(n + 1);
dp[1] = 1;
sum[1] = 1;
for (int i = 2; i <= n; i++) {
int start = max(0, i - forget);
int end = max(0, i - delay);
dp[i] = (sum[end] - sum[start] + mod) % mod;
sum[i] = sum[i - 1] + dp[i];
}
return (sum[n] - sum[max(0, n - forget)] + mod) % mod;
}
}; - 解法二:
class Solution {
public:
int peopleAwareOfSecret(int n, int delay, int forget) {
vector<long long> dp(forget);
long long mod = 1e9 + 7;
dp[0] = 1;
for (int i = 2; i <= n; i++) {
for (int j = forget - 1; j >= 1; j--) {
dp[j] = dp[j - 1];
}
dp[0] = 0;
for (int j = delay; j < forget; j++) {
dp[0] = (dp[0] + dp[j]) % mod;
}
}
long long ans = 0;
for (int i = 0; i < forget; i++) {
ans = (ans + dp[i]) % mod;
}
return ans;
}
};
6110. 网格图中递增路径的数目
题目
给你一个 m x n
的整数网格图 grid
,你可以从一个格子移动到 4
个方向相邻的任意一个格子。
请你返回在网格图中从 任意 格子出发,达到 任意 格子,且路径中的数字是 严格递增 的路径数目。由于答案可能会很大,请将结果对 109 + 7
取余 后返回。
如果两条路径中访问过的格子不是完全相同的,那么它们视为两条不同的路径。
示例 1:
输入:grid = [[1,1],[3,4]] |
示例 2:
输入:grid = [[1],[2]] |
提示:
m == grid.length
n == grid[i].length
1 <= m, n <= 1000
1 <= m * n <= 105
1 <= grid[i][j] <= 105
地址
https://leetcode.cn/contest/weekly-contest-300/problems/number-of-increasing-paths-in-a-grid/
题意
动态规划
思路
- 非常简单的动态规划,题目要求严格递增,首先我们想到的就是将矩阵中的数字按照大小进行排列,设 $dp[i][j]$ 表示 以 $(i,j)$ 为结尾且严格递增的路径数目,此时我们可以知道如下递推关系:
$$
dp[i][j] = (dp[i][j] + dp[i][j-1]) \quad if(grid[i][j] > grid[i][j-1])\
dp[i][j] = (dp[i][j] + dp[i-1][j]) \quad if(grid[i][j] > grid[i-1][j])\
dp[i][j] = (dp[i][j] + dp[i][j+1]) \quad if(grid[i][j] > grid[i][j+1])\
dp[i][j] = (dp[i][j] + dp[i+1][j]) \quad if(grid[i][j] > grid[i+1][j])\
$$
由于满足了严格的大小关系,所以所有严格小于 $dp[i][j]$ 的序列数目已经确定。 - 只需要满足严格递增即可,感觉就非常简单了,不过可以稍微修改一点增加难度,比如非严格递增怎么解决?
- 复杂度分析:
- 时间复杂度:$m \times n$, $m, n$ 表示矩阵的行数与列数。
- 空间复杂度:$m \times n$, $m, n$ 表示矩阵的行数与列数。
代码
class Solution { |
欢迎关注和打赏,感谢支持!
- 关注我的博客: http://mikemeng.org/
- 关注我的知乎:https://www.zhihu.com/people/da-hua-niu
- 关注我的微信公众号: 公务程序猿
扫描二维码,分享此文章