LeetCode 2024/6 每日一题 合集
2024-6-1 2928. 给小朋友们分糖果 I
分析
枚举所有可能的方案数即可
代码实现
class Solution {
public:
int distributeCandies(int n, int limit) {
int ans = 0;
for (int a = 0; a <= limit; ++a) {
for (int b = 0; b + a <= n && b <= limit; ++b) {
for (int c = 0; a + b + c <= n && c <= limit; ++c) {
ans += a + b + c == n;
}
}
}
return ans;
}
};
2024-6-2 575. 分糖果
代码实现
class Solution {
public:
int distributeCandies(vector<int>& a) {
return std::min<int>(std::set<int>(a.begin(), a.end()).size(), size(a) / 2);
}
};
2024-6-3 1103. 分糖果 II
分析
发现如果每次暴力发放\(n + 1\)颗糖果时间复杂度为\(O(\sqrt n)\),因此选择直接枚举
代码实现
class Solution {
public:
vector<int> distributeCandies(int candies, int num_people) {
std::vector<int> ans(num_people);
int cur = 1;
while (candies > 0) {
ans[(cur - 1 + num_people) % num_people] += std::min(cur, candies);
candies -= cur++;
}
return ans;
}
};
2024-6-4 3067. 在带权树网络中统计可连接服务器对数目
分析
枚举当前根下存在多少对\((a, b)\)即可,跑两边dfs,第一遍求出root到所有点的距离记录根儿子下符合条件的点有多少,最后数目即为\(\frac{\sum当前儿子符合条件数*其余儿子符合条件数}{2}\)
代码实现
class Solution {
public:
vector<int> countPairsOfConnectableServers(vector<vector<int>>& edges, int signalSpeed) {
int n = size(edges) + 1;
std::vector<std::vector<std::pair<int, int>>> g(n);
for (auto edge : edges) {
int a = edge[0], b = edge[1], c = edge[2];
g[a].emplace_back(b, c);
g[b].emplace_back(a, c);
}
std::vector<int> count(n);
for (int root = 0; root < n; ++root) {
int cnt = -1;
std::vector<int> dist(n);
auto dfs_dis = [&](auto &&self, int u, int fa)->void {
cnt += dist[u] % signalSpeed == 0;
for (auto [v, w] : g[u]) if (v != fa) {
dist[v] = dist[u] + w;
self(self, v, u);
}
};
dfs_dis(dfs_dis, root, -1);
auto dfs = [&](auto &&self, int u, int fa)->int {
int num = dist[u] % signalSpeed == 0;
for (auto [v, w] : g[u]) if (v != fa) {
int t = self(self, v, u);
if (fa == -1) {
count[root] += t * (cnt - t);
}
num += t;
}
return num;
};
dfs(dfs, root, -1);
count[root] /= 2;
}
return count;
}
};
2024-6-5 3072. 将元素分配到两个数组中 II
分析
本题的难度在于如何快速查找数组中严格大于val
的位置,可以选择使用离散化加树状数组进行维护。
代码实现
template<typename T>
struct Fenwick {
const int n;
std::vector<T> tr;
Fenwick(int n) : n(n), tr(n + 1) {}
void add(int x, T c) {
for (int i = x; i <= n; i += i & -i) tr[i] += c;
}
void add(int l, int r, T c) {
add(l, c);
if (r + 1 <= n) add(r + 1, -c);
}
T get(int x) {
T res = T();
for (int i = x; i > 0; i -= i & -i) res += tr[i];
return res;
}
T get(int l, int r) {
return get(r) - get(l - 1);
}
int find_first(T sum) {
int ans = 0; T val = 0;
for (int i = std::__lg(n); i >= 0; --i) {
if ((ans | (1 << i)) <= n and val + tr[ans | (1 << i)] < sum) {
ans |= 1 << i;
val += tr[ans];
}
}
return ans + 1;
}
int find_last(T sum) {
int ans = 0; T val = 0;
for (int i = std::__lg(n); i >= 0; --i) {
if ((ans | (1 << i)) <= n and val + tr[ans | (1 << i)] <= sum) {
ans |= 1 << i;
val += tr[ans];
}
}
return ans;
}
};
using BIT = Fenwick<int>;
class Solution {
public:
vector<int> resultArray(vector<int>& nums) {
int n = size(nums);
std::vector<int> ord(n);
std::iota(ord.begin(), ord.end(), 0);
std::sort(ord.begin(), ord.end(),
[&](int x, int y) {
return nums[x] < nums[y];
});
for (int i = 0; i < n; ++i) {
while (i + 1 < n && nums[ord[i]] == nums[ord[i + 1]]) {
ord[i + 1] = ord[i];
i += 1;
}
}
std::unordered_map<int, int> mp;
for (int i = 0; i < n; ++i) {
if (!mp.count(nums[ord[i]])) {
mp[nums[ord[i]]] = i + 1;
}
}
auto greaterCount = [&](BIT &bit, int val) {
return bit.get(mp[val], n) - bit.get(mp[val], mp[val]);
};
BIT bit1(n + 2), bit2(n + 2);
std::vector<int> arr1{nums[0]}, arr2{nums[1]};
bit1.add(mp[nums[0]], +1), bit2.add(mp[nums[1]], +1);
for (int i = 2; i < n; ++i) {
int p1 = greaterCount(bit1, nums[i]);
int p2 = greaterCount(bit2, nums[i]);
if (p1 > p2) {
arr1.emplace_back(nums[i]);
bit1.add(mp[nums[i]], +1);
} else if (p1 < p2) {
arr2.emplace_back(nums[i]);
bit2.add(mp[nums[i]], +1);
} else {
if (size(arr1) <= size(arr2)) {
arr1.emplace_back(nums[i]);
bit1.add(mp[nums[i]], +1);
} else {
arr2.emplace_back(nums[i]);
bit2.add(mp[nums[i]], +1);
}
}
// debug(arr1, arr2);
}
std::vector<int> result;
result.insert(result.end(), arr1.begin(), arr1.end());
result.insert(result.end(), arr2.begin(), arr2.end());
return result;
}
};
2024-6-6 2938. 区分黑球与白球
分析
可以发现每个白球都有最终的固定位置,求一下所有白球到最终位置的距离即可
代码实现
class Solution {
public:
long long minimumSteps(string s) {
int n = size(s);
long long ans = 0;
for (int i = 0, j = 0; i < n; ++i) {
if (s[i] == '0') {
ans += i - j;
j += 1;
}
}
return ans;
}
};
2024-6-7 3038. 相同分数的最大操作数目 I
代码实现
class Solution {
public:
int maxOperations(vector<int>& nums) {
int same = nums[0] + nums[1], cnt = 1;
for (int i = 2; i < size(nums); i += 2) {
if (nums[i] + nums[i + 1] == same) {
cnt += 1;
} else {
break;
}
}
return cnt;
}
};
2024-6-8 3040. 相同分数的最大操作数目 II
代码实现
class Solution {
public:
int maxOperations(vector<int>& nums) {
int n = size(nums);
std::vector<int> cnt(n * n + 10100);
cnt[2 * n + n - 1 + 1001] = cnt[1 * n + n - 2 + 1001] = cnt[0 * n + n - 3 + 1001] = 1;
auto dfs = [&](auto &&self, int val, int l, int r) {
// debug(val, l, r);
if (r - l < 1) return ;
// debug(val, l, r);
if (nums[r] + nums[r - 1] == val && cnt[l * n + r - 2 + 1001] < cnt[l * n + r + 1001] + 1) {
cnt[l * n + r - 2 + 1001] = cnt[l * n + r + 1001] + 1;
self(self, val, l, r - 2);
}
if (nums[r] + nums[l] == val && cnt[(l + 1) * n + r - 1 + 1001] < cnt[l * n + r + 1001] + 1) {
cnt[(l + 1) * n + r - 1 + 1001] = cnt[l * n + r + 1001] + 1;
self(self, val, l + 1, r - 1);
}
if (nums[l] + nums[l + 1] == val && cnt[(l + 2) * n + r + 1001] < cnt[l * n + r + 1] + 1001) {
cnt[(l + 2) * n + r + 1001] = cnt[l * n + r + 1001] + 1;
self(self, val, l + 2, r);
}
};
dfs(dfs, nums[0] + nums[1], 2, n - 1);
dfs(dfs, nums[0] + nums[n - 1], 1, n - 2);
dfs(dfs, nums[n - 1] + nums[n - 2], 0, n - 3);
return std::ranges::max(cnt);
}
};
2024-6-9 312. 戳气球
代码实现
class Solution {
public:
int maxCoins(vector<int>& nums) {
int n = size(nums);
std::vector val(n + 2, 1);
for (int i = 1; i <= n; ++i) {
val[i] = nums[i - 1];
}
std::vector<std::vector<int>> f(n + 2, std::vector<int>(n + 2));
for (int len = 3; len <= n + 2; ++len) {
for (int l = 0; l + len - 1 <= n + 1; ++l) {
int r = l + len - 1;
for (int k = l + 1; k < r; ++k) {
f[l][r] = std::max(f[l][r], f[l][k] + f[k][r] + val[l] * val[k] * val[r]);
}
}
}
return f[0][n + 1];
}
};
2024-6-10 881. 救生艇
代码实现
class Solution {
public:
int numRescueBoats(vector<int>& people, int limit) {
int n = size(people);
std::sort(people.begin(), people.end());
int l = 0, r = n - 1, ans = 0;
while (l <= r) {
if (people[l] + people[r] <= limit) {
l += 1, r -= 1, ans += 1;
} else {
r -= 1, ans += 1;
}
}
return ans;
}
};
2024-6-11 419. 甲板上的战舰
代码实现
class Solution {
public:
int countBattleships(vector<vector<char>>& board) {
int m = size(board), n = size(board[0]);
int ans = 0;
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (board[i][j] == 'X' && (i == 0 || board[i - 1][j] != 'X') && (j == 0 || board[i][j - 1] != 'X')) {
ans += 1;
}
}
}
return ans;
}
};
2024-6-12 2806. 取整购买后的账户余额
代码实现
class Solution {
public:
int accountBalanceAfterPurchase(int purchaseAmount) {
return 100 - (int)((double)purchaseAmount / 10 + 0.5) * 10;
}
};
2024-6-13 2813. 子序列最大优雅度
分析
显然的对于小于k的首次出现的\(profit_i\)必取,对于相同的\(category_i\)可以先加入栈,看后续是否有更优解进行替换。
代码实现
class Solution {
public:
long long findMaximumElegance(vector<vector<int>>& items, int k) {
int n = size(items);
std::sort(items.begin(), items.end(),
[&](const std::vector<int> &x, const std::vector<int> &y) {
return x[0] != y[0] ? x[0] > y[0] : x[1] > y[1];
});
std::map<int, int> mp;
long long ans = 0, sum = 0;
std::vector<std::pair<int, int>> stk;
for (int i = 0; i < n; ++i) {
if (i < k) {
sum += items[i][0];
if (mp.count(items[i][1])) {
stk.emplace_back(items[i][0], items[i][1]);
}
mp[items[i][1]] += 1;
} else if (!mp.count(items[i][1]) && size(stk) != 0) {
sum += items[i][0] - stk.rbegin()[0].first;
stk.pop_back();
mp[items[i][1]] += 1;
}
ans = std::max<long long>(ans, size(mp) * size(mp) + sum);
}
return ans;
}
};
2024-6-14 2786. 访问数组中的位置使分数最大
代码实现
class Solution {
public:
long long maxScore(vector<int>& nums, int x) {
int n = size(nums);
std::vector<std::array<long long, 2>> f(n, {(long long)-1e9, (long long)-1e9});
f[0][nums[0] & 1] = nums[0];
for (int i = 1; i < n; ++i) {
int v = nums[i] & 1;
f[i] = f[i - 1];
f[i][v] = std::max(f[i][v], f[i][v ^ 1] - x) + nums[i];
}
return std::max(f[n - 1][0], f[n - 1][1]);
}
};
2024-6-15 2786. 访问数组中的位置使分数最大
分析
差分,转换成区间最大值
代码实现
class Solution {
public:
int maximumBeauty(vector<int>& nums, int k) {
int n = size(nums);
const int W = 1e5;
for (int i = 0; i < n; ++i) {
nums[i] += W;
}
std::vector<int> pre(W * 3 + 2);
for (int i = 0; i < n; ++i) {
pre[nums[i] - k] += 1;
pre[nums[i] + k + 1] -= 1;
}
for (int i = 1; i <= 3 * W; ++i) {
pre[i] += pre[i - 1];
}
return std::ranges::max(pre);
}
};
2024-6-16 2786. 访问数组中的位置使分数最大
代码实现
class Solution {
public:
int findLUSlength(string a, string b) {
if (a != b) {
return std::max(size(a), size(b));
} else {
return -1;
}
}
};
2024-6-17 522. 最长特殊序列 II
分析
直接贪心枚举即可
代码实现
class Solution {
public:
int findLUSlength(vector<string>& strs) {
int n = size(strs);
std::sort(strs.begin(), strs.end(),
[&](const std::string &a, const std::string&b) {
return size(a) > size(b);
});
auto check = [&](const std::string &s, const std::string &t) {
int idx = 0;
for (auto c : t) {
if (s[idx] == c && ++idx == size(s)) {
return true;
}
}
return false;
};
for (int i = 0; i < n; ++i) {
bool ok = true;
for (int j = 0; j < n; ++j) if (i != j && check(strs[i], strs[j])) {
ok = false;
}
if (ok) return size(strs[i]);
}
return -1;
}
};
2024-6-18 2288. 价格减免
代码实现
class Solution {
public:
string discountPrices(string sentence, int discount) {
std::stringstream cin(sentence), cout;
cout << std::fixed << std::setprecision(2);
std::vector<std::string> strs;
std::string s;
while (cin >> s) {
strs.push_back(s);
}
// debug(strs);
for (auto &str : strs) {
if (str[0] == '$' && size(str) > 1 && std::all_of(str.begin() + 1, str.end(), ::isdigit)) {
double price = std::stod(str.substr(1)) * (1.0 - (double)discount / 100);
cout << '$' << price << ' ';
} else {
cout << str << ' ';
}
}
std::string ans = cout.str();
ans.pop_back();
return ans;
}
};
2024-6-19 2713. 矩阵中严格递增的单元格数
代码实现
class Solution {
public:
int maxIncreasingCells(vector<vector<int>>& mat) {
int n = size(mat), m = size(mat[0]);
std::map<int, std::vector<std::pair<int, int>>> mp;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
mp[mat[i][j]].emplace_back(i, j);
}
}
std::vector<int> col_max(m), row_max(n);
for (auto [_, pos] : mp) {
std::vector<int> f;
for (auto [x, y] : pos) {
f.push_back(std::max(row_max[x], col_max[y]) + 1);
}
for (int i = 0; i < size(pos); i++) {
auto [x, y] = pos[i];
row_max[x] = std::max(row_max[x], f[i]);
col_max[y] = std::max(col_max[y], f[i]);
}
}
return std::ranges::max(row_max);
}
};
2024-6-20 2748. 美丽下标对的数目
代码实现
class Solution {
public:
int countBeautifulPairs(vector<int>& nums) {
int sum = 0;
for (int i = 0; i < size(nums); ++i) {
while (nums[i] >= 10) nums[i] /= 10;
for (int j = i + 1; j < size(nums); ++j) {
sum += std::gcd(nums[i], nums[j] % 10) == 1;
}
}
return sum;
}
};
2024-6-21 LCP 61. 气温变化趋势
代码实现
class Solution {
public:
int temperatureTrend(vector<int>& A, vector<int>& B) {
int ans = 0, same = 0;
auto cmp = [&](int a, int b) {
return a > b ? -1 : a == b;
};
for (int i = 1; i < size(A); ++i) {
if (cmp(A[i], A[i - 1]) == cmp(B[i], B[i - 1])) {
same += 1;
ans = std::max(ans, same);
} else same = 0;
}
return ans;
}
};
2024-6-22 2663. 字典序最小的美丽字符串
分析
发现只要不存在\(s_i = s_{i-1}\)和\(s_i = s_{i - 2}\),则一定不存在大于等于2回文串,因此只需要贪心的维护即可。
代码实现
class Solution {
public:
string smallestBeautifulString(string s, int k) {
int n = size(s);
int idx = n - 1;
s[idx] += 1;
while (idx < n) {
if (s[idx] - 'a' == k) {
if (idx == 0) return "";
s[idx] = 'a', s[--idx] += 1;
} else if (idx > 0 && s[idx] == s[idx - 1] || idx > 1 && s[idx] == s[idx - 2]) {
s[idx] += 1;
} else {
idx += 1;
}
}
return s;
}
};
2024-6-23 520. 检测大写字母
代码实现
class Solution {
public:
bool detectCapitalUse(string word) {
bool ok = true;
for (int i = 2; i < size(word); ++i) {
ok &= islower(word[i]) == islower(word[i - 1]);
}
if (size(word) != 1 && (!ok || word[0] >= 'a' && word[1] <= 'Z')) {
return false;
}
return true;
}
};
2024-6-24 503. 下一个更大元素 II
代码实现
class Solution {
public:
vector<int> nextGreaterElements(vector<int>& nums) {
int n = size(nums);
std::vector<int> ans(n, -1), stk;
for (int i = 0; i < 2 * n - 1; ++i) {
while (size(stk) && nums[stk.back()] < nums[i % n]) {
ans[stk.back()] = nums[i % n];
stk.pop_back();
}
stk.emplace_back(i % n);
}
return ans;
}
};
2024-6-25 2732. 找到矩阵中的好子集
分析
发现\(n\)非常小,种类最多为\(2^n\)个,因此直接记录所有种类所在的位置,最后再进行枚举即可。
代码实现
class Solution {
public:
vector<int> goodSubsetofBinaryMatrix(vector<vector<int>>& grid) {
std::unordered_map<int, int> mp;
for (int i = 0; i < size(grid); ++i) {
int cost = 0;
for (int j = 0; j < size(grid[i]); ++j){
cost |= grid[i][j] << j;
}
mp[cost] = i;
if (cost == 0) return {i};
}
for (auto [x, a] : mp) {
for (auto [y, b] : mp) {
if ((x & y) == 0) {
return {std::min(a, b), std::max(a, b)};
}
}
}
return {};
}
};
2024-6-26 2741. 特别的排列
代码实现
using LL = long long;
class Solution {
public:
int specialPerm(vector<int>& nums) {
const int P = 1e9 + 7;
int n = size(nums);
std::vector f((1 << n) - 1, std::vector<LL>(n, -1));
auto dfs = [&](auto &&self, int s, int t)->LL {
if (s == 0) return 1;
LL &u = f[s][t];
if (u != -1) return u;
u = 0;
for (int i = 0; i < n; ++i) {
if ((s >> i & 1) && (nums[i] % nums[t] == 0 || nums[t] % nums[i] == 0)) {
u += self(self, s ^ (1 << i), i);
}
}
return u;
};
LL ans = 0;
for (int i = 0; i < n; ++i) {
ans += dfs(dfs, (1 << n) - 1 ^ (1 << i), i);
ans %= P;
}
return ans;
}
};
2024-6-27 2734. 执行子串操作后的字典序最小字符串
代码实现
class Solution {
public:
string smallestString(string s) {
if (std::count(s.begin(), s.end(), 'a') == size(s)) {
s.rbegin()[0] = 'z';
return s;
}
int idx = 0;
while (idx < (int)size(s) && s[idx] == 'a') {
idx += 1;
}
while (idx < (int)size(s) && s[idx] != 'a') {
s[idx]--;
idx += 1;
}
return s;
}
};
2024-6-28 2742. 给墙壁刷油漆
代码实现
class Solution {
public:
int paintWalls(vector<int>& cost, vector<int>& time) {
int n = size(cost);
std::vector<int> f(n + 1, 1e9);
f[0] = 0;
for (int i = 0; i < n; ++i) {
for (int j = n; j >= 0; --j) {
f[j] = std::min(f[j], f[std::max(j - time[i] - 1, 0)] + cost[i]);
}
}
return f[n];
}
};
2024-6-29 2710. 移除字符串中的尾随零
代码实现
class Solution {
public:
string removeTrailingZeros(string num) {
int p = size(num) - 1;
while (p >= 1 && num[p] == '0') {
p--;
}
return num.substr(0, p + 1);
}
};
2024-6-30 494. 目标和
代码实现
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int target) {
int n = size(nums);
int ans = 0;
auto dfs = [&](auto &&self, int u, int cost)->void {
if (u == n) {
ans += target == cost;
return ;
}
self(self, u + 1, cost + nums[u]);
self(self, u + 1, cost - nums[u]);
};
dfs(dfs, 0, 0);
return ans;
}
};