感冒了,周末一直发烧。各位老铁记得记得多喝热水,谨防感冒🤧。
周赛传送门
2042. 检查句子中的数字是否递增
思路:字符串分割
时间复杂度:
可以按空格分割,然后转化为数字依次比较即可。
class Solution {
public:
bool areNumbersAscending(string s) {
// pre 记录前一个数字
// now 记录刚刚转化得到的数字
int pre = -1, now = -1;
// 默认放入一个空格,这样使得每个 word 后都有一个空格,方便处理。
s.push_back(' ');
for (int i = 0; i < s.size(); i++) {
if (s[i] >= '0' && s[i] <= '9') {
now = (now == -1) ? (s[i]-'0') : (now*10 + s[i]-'0');
} else {
if (now != -1) {
if (now <= pre) {
return false;
}
pre = now;
now = -1;
}
}
}
return true;
}
};
2043. 简易银行系统
思路:模拟
时间复杂度:, 为操作次数, 为用户数量。
比较简单的模拟题啦,直接把题目翻译成代码就好啦。
class Bank {
public:
vector<long long> bal;
Bank(vector<long long>& b) {
bal.reserve(b.size() + 1);
bal.emplace_back(0); // 添加一份冗余数据,对齐账户编号和下标。
bal.insert(bal.end(), b.begin(), b.end());
}
bool transfer(int a1, int a2, long long money) {
if (a1 < 1 || bal.size() < a1 || a2 < 1 || bal.size() < a2) {
return false;
}
if (bal[a1] < money) {
return false;
}
bal[a1] -= money;
bal[a2] += money;
return true;
}
bool deposit(int account, long long money) {
if (account < 1 || bal.size() < account) {
return false;
}
bal[account] += money;
return true;
}
bool withdraw(int account, long long money) {
if (account < 1 || bal.size() < account) {
return false;
}
if (bal[account] < money) {
return false;
}
bal[account] -= money;
return true;
}
};
/**
* Your Bank object will be instantiated and called as such:
* Bank* obj = new Bank(balance);
* bool param_1 = obj->transfer(account1,account2,money);
* bool param_2 = obj->deposit(account,money);
* bool param_3 = obj->withdraw(account,money);
*/
2044. 统计按位或能得到最大值的子集数目
思路:位运算
时间复杂度:
空间复杂度:
枚举所有子集,然后计算每个子集的值即可。
class Solution {
public:
int countMaxOrSubsets(vector<int>& nums) {
int mask = (1<< nums.size());
// val 用于存储最大值
// cnt 存储次数
int val = -1, cnt = 0;
// 枚举状态 i
for (int i = 0; i < mask; i++) {
int v = 0;
// 计算状态 i 的值
for (int j = 0, b = 1; j < nums.size(); j++, b<<=1) {
if (i&b) {
v |= nums[j];
}
}
// 尝试更新最大值以及次数。
if (v > val) {
val = v, cnt = 1;
} else if (v == val) {
cnt++;
}
}
return cnt;
}
};
思路:动态规划
时间复杂度:
空间复杂度:
除空集外,每个子集都可由另一个子集添加一个数字得到。因此不难想到:
其中,
class Solution {
public:
int countMaxOrSubsets(vector<int>& nums) {
int mask = (1<< nums.size());
// val 用于存储最大值
// cnt 存储次数
int val = 0, cnt = 1;
vector<int> dp(mask, 0);
// 初始化仅含单个数字的集合
for (int i = 0; i < nums.size(); i++) {
dp[1<<i] = nums[i];
}
// 枚举状态 i
for (int i = 1; i < mask; i++) {
int j = i&(i-1);
int k = i^j;
dp[i] = dp[j] | dp[k];
// 尝试更新最大值以及次数。
if (dp[i] > val) {
val = dp[i], cnt = 1;
} else if (dp[i] == val) {
cnt++;
}
}
return cnt;
}
};
2045. 到达目的地的第二短时间
思路:BFS
时间复杂度:
先考虑没有红绿灯的情况,该题就是一个标准的 BFS 题目。
先回忆一下BFS求最短路的过程,设有数组 , 表示节点 到 的最短距离。每次从队首取出节点 ,设 是 相邻节点,当且仅当 成立时 进入队列,其中 为边权。
为求次短路,需引入数组 ,表示节点 到 的严格次短距离。为了更新两个距离数组,每个节点需进入队列两次。为了便于区分,队列需记录节点编号及距离。
从队首取出节点及距离,设 是 的相邻节点。当且仅当满足下述条件之一时, 加入队列。
- , 加入队列
- 且 , 加入队列
接下来考虑,引入红绿灯后 BFS 的正确性。
因此所有节点的红绿灯切换是一致的,且每条边的权值相同,所以走过两条长度相同的路径,其等待红灯的时间必然相同,因此总时间也相同。
而走过较长的路径,其等待红灯的时间必然不小于较短的路径。因此引入红绿灯后,较短路径的总时间仍小于较长的路径。
甚至,由于红灯的可预见性,我们可以在找出次短路之后,再计算引入红绿灯之后的总时长。
class Solution {
public:
int secondMinimum(int n, vector<vector<int>>& edges, int time, int change) {
// 建立边表
vector<int> edge[10001];
for (const auto &e : edges) {
edge[e[0]].push_back(e[1]);
edge[e[1]].push_back(e[0]);
}
// 初始化距离数组
vector<vector<int>> dis(n+1, vector<int>(2, INT_MAX));
dis[1][0] = 0;
// 将源点加入队列
queue<pair<int, int>> q;
q.push(make_pair(1, 0));
// 开始BFS
while(!q.empty()) {
// 取出队首的元素(u,d)
auto f = q.front();
q.pop();
int u = f.first;
int d = f.second;
// 遍历相邻节点 v
for (auto v : edge[u]) {
int cost = d + 1; // 到达相邻节点的距离为 d + 1
// d+1 < d0[v]
if (cost < dis[v][0]) {
dis[v][1] = dis[v][0];
dis[v][0] = cost;
q.push(make_pair(v, cost));
}
// d0[v] < d+1 && d+1 < d1[v]
else if (dis[v][0] < cost && cost < dis[v][1]) {
dis[v][1] = cost;
q.push(make_pair(v, cost));
}
}
}
// len 是次短路的长度,即次短路包含的边数
int len = dis[n][1];
// cost 为走过次短路的总时长
int cost = 0;
for (int i = 0; i < len; i++) {
// 到达路径上第 i 个点的时间点为 cost
// 如果 (cost / change) 是个奇数,说明此时是红灯,需等待change - cost%change
if ((cost / change)&1) {
cost += change - cost%change;
}
// 再加上 i -> i+1 所需的时间,即走过一条边的时间。
cost += time;
}
return cost;
}
};