Leetcode 第 401 场周赛题解
- Leetcode 第 401 场周赛题解
- 题目1:3178. 找出 K 秒后拿着球的孩子
- 思路
- 代码
- 复杂度分析
- 题目2:3179. K 秒后第 N 个元素的值
- 思路
- 代码
- 复杂度分析
- 题目3:3180. 执行操作可获得的最大总奖励 I
- 思路
- 代码
- 复杂度分析
- 题目4:3181. 执行操作可获得的最大总奖励 II
- 思路
- 代码
- 复杂度分析
Leetcode 第 401 场周赛题解
题目1:3178. 找出 K 秒后拿着球的孩子
思路
根据趟数的奇偶性,进而确定位置。
代码
/*
* @lc app=leetcode.cn id=3178 lang=cpp
*
* [3178] 找出 K 秒后拿着球的孩子
*/
// @lc code=start
class Solution
{
public:
int numberOfChild(int n, int k)
{
if (k < n)
return k;
if ((k / (n - 1)) % 2)
return n - 1 - k % (n - 1);
return k % (n - 1);
}
};
// @lc code=end
复杂度分析
时间复杂度:O(1)。
空间复杂度:O(1)。
题目2:3179. K 秒后第 N 个元素的值
思路
模拟 k 轮,数组保存上一次结果,然后计算当前轮次的结果。
代码
/*
* @lc app=leetcode.cn id=3179 lang=cpp
*
* [3179] K 秒后第 N 个元素的值
*/
// @lc code=start
class Solution
{
private:
const int MOD = 1e9 + 7;
public:
int valueAfterKSeconds(int n, int k)
{
int a[n];
for (int i = 0; i <= k; i++)
{
for (int j = 0; j < n; j++)
{
if (j == 0 || i == 0)
a[j] = 1;
else
a[j] = (a[j] + a[j - 1]) % MOD;
}
}
return a[n - 1];
}
};
// @lc code=end
复杂度分析
时间复杂度:O(n*k)。
空间复杂度:O(n)。
题目3:3180. 执行操作可获得的最大总奖励 I
思路
记忆化搜索。
选或不选,递归地求最大总奖励。
代码
#
# @lc app=leetcode.cn id=3180 lang=python3
#
# [3180] 执行操作可获得的最大总奖励 I
#
# @lc code=start
class Solution:
def maxTotalReward(self, rewardValues: List[int]) -> int:
rewardValues.sort()
@cache
def dfs(i: int) -> int:
res = 0
for x in rewardValues:
if i < x:
res = max(res, dfs(i + x) + x)
return res
return dfs(0)
# @lc code=end
复杂度分析
时间复杂度:O(nlogn),其中 n 是数组 rewardValues 的长度。
空间复杂度:O(logn),其中 n 是数组 rewardValues 的长度。
题目4:3181. 执行操作可获得的最大总奖励 II
思路
bitset/bigint 优化 0-1 背包
对于数组 rewardValues 中的数,如果先选大的,就没法再选小的,所以按照从小到大的顺序选是最好的。
把 rewardValues 从小到大排序。
排序后,问题变成一个标准的 0-1 背包问题。
对于本题,定义 f[i][j] 表示能否从前 i 个数中得到总奖励 j。
本题范围很大,需要去掉第一个维度,并用 bitset 优化(也可以用 bigint)。
代码
/*
* @lc app=leetcode.cn id=3181 lang=cpp
*
* [3181] 执行操作可获得的最大总奖励 II
*/
// @lc code=start
class Solution
{
public:
int maxTotalReward(vector<int> &rewardValues)
{
ranges::sort(rewardValues);
rewardValues.erase(unique(rewardValues.begin(), rewardValues.end()), rewardValues.end());
bitset<100000> f{1};
for (int v : rewardValues)
{
int shift = f.size() - v;
// 左移 shift 再右移 shift,把所有 >= v 的比特位置 0
// f |= f << shift >> shift << v;
f |= f << shift >> (shift - v); // 简化上式
}
for (int i = rewardValues.back() * 2 - 1;; i--)
if (f.test(i))
return i;
}
};
// @lc code=end
复杂度分析
时间复杂度:O(n*m/w),其中 n 是数组 rewardValues 的长度,m=max(rewardValues),w =64 或 32。
空间复杂度:O(n+m/w),其中 n 是数组 rewardValues 的长度,m=max(rewardValues),w =64 或 32。