力扣每月题解汇总-2026年09月

目录


力扣每日一题3568-清理教室的最少移动

日期:2026-09-01

题意

给定含 障碍物 垃圾 充能区 的网格图 classroom, 初始有 energy 的能量. 每走一步需要消耗 1 能量, 经过回能区时会将能量恢复为 energy, 经过垃圾时可清理掉垃圾, 问从起点出发到清理掉所有垃圾所需的最小步数.

思路

那应该是做一个 bfs, 只是状态多了当前已清理掉的垃圾以及所剩能量.

实现

class Solution {
static constexpr array<int, 2> nxt[] = {
{-1, 0}, {1, 0}, {0, -1}, {0, 1}
};
public:
int minMoves(vector<string>& classroom, int energy) {
int n = classroom.size(), m = classroom.back().size();
vector mp(n, vector<int> (m));
int sx, sy;
int p = 0;
for (int i = 0, t = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (classroom[i][j] == 'S') {
sx = i;
sy = j;
} else if (classroom[i][j] == 'L') {
mp[i][j] = 1 << t;
p |= 1 << t;
t++;
}
}
}

queue<array<int, 5>> q;
q.push({sx, sy, energy, 0, 0});
vector vis(n, vector (m, vector<int> (p, -1)));
while (!q.empty()) {
auto [x, y, e, cur, t] = q.front();
q.pop();
if (cur == p) return t;
if (e == 0) continue;
int& d = vis[x][y][cur];
if (d >= e) continue;
d = e;
for (auto [tx, ty] : nxt) {
int nx = tx + x, ny = ty + y;
if (nx < 0 || nx >= n || ny < 0 || ny >= m || classroom[nx][ny] == 'X') continue;
q.push({nx, ny, classroom[nx][ny] == 'R' ? energy : e - 1, cur | mp[nx][ny], t + 1});
}
}
return -1;
}
};

力扣每日一题3875-构造奇偶一致的数组I

日期:2026-09-02

题意

给定一个数组 nums1, 问是否可以从中组成等长新数组 nums2 满足 (nums2[i] == nums1[i]) OR (nums2[i] == nums1[i] - nums1[j] AND i != j), 同时 nums2 中所有数奇偶性相同.

思路

注意到偶数减奇数为奇数, 因此其实所有情况下都是可以组成的.

实现

class Solution {
public:
bool uniformArray(vector<int>& nums1) {
return true;
}
};

力扣每日一题3876-构造奇偶一致的数组II

日期:2026-09-03

题意

给定一个数组 nums1, 问是否可以从中组成等长新数组 nums2 满足 (nums2[i] == nums1[i]) OR (nums2[i] == nums1[i] - nums1[j] AND i != j AND nums1[i] - nums1[j] >= 1), 同时 nums2 中所有数奇偶性相同.

思路

在昨天题意的基础上加上了 nums1[i] - nums1[j] >= 1 的条件, 换言之当前位置的数要比减数大, 也就是说最小偶数要比最小奇数大.

实现

class Solution {
public:
bool uniformArray(vector<int>& nums1) {
int odd = 0, even = 0, mnodd = INT_MAX, mneven = INT_MAX;
for (auto& x : nums1) {
if (x & 1) {
odd++;
mnodd = min(mnodd, x);
} else {
even++;
mneven = min(mneven, x);
}
}
if (even == 0 || odd == 0) return true;
return mneven > mnodd;
}
};

力扣每日一题3903-最小稳定下标I

日期:2026-09-04

题意

给定非负整数数组 nums; 定义若某位置的前缀最大值减去后缀最小值不超过 k 则称其为稳定位置. 求该数组中最早出现的稳定位置.

思路

那做一个后缀 min, 再从前往后做个前缀 max 找符合条件的点即可.

实现

class Solution {
public:
int firstStableIndex(vector<int>& nums, int k) {
int n = nums.size();
vector<int> suf(n);
suf[n - 1] = nums.back();
for (int i = n - 2; i >= 0; i--) {
suf[i] = min(suf[i + 1], nums[i]);
}
for (int i = 0, mx = 0; i < n; i++) {
mx = max(mx, nums[i]);
if (mx - suf[i] <= k) return i;
}
return -1;
}
};

力扣每日一题3904-最小稳定下标II

日期:2026-09-05

题意

给定非负整数数组 nums; 定义若某位置的前缀最大值减去后缀最小值不超过 k 则称其为稳定位置. 求该数组中最早出现的稳定位置.

思路

和昨天题意一样, 只是数据增强. 但我们昨天的做法仍是可行的, 做一个后缀min再做一个前缀max就好.

实现

class Solution {
public:
int firstStableIndex(vector<int>& nums, int k) {
int n = nums.size();
vector<int> suf(n);
suf[n - 1] = nums.back();
for (int i = n - 2; i >= 0; i--) {
suf[i] = min(suf[i + 1], nums[i]);
}
for (int i = 0, mx = 0; i < n; i++) {
mx = max(mx, nums[i]);
if (mx - suf[i] <= k) return i;
}
return -1;
}
};

力扣每日一题115-不同的子序列

日期:2026-09-06

题意

给定两个字符串 st, 求问 s 的子序列中 t 的出现次数.

思路

那应该是做一个 dp, 枚举每个 s 的前缀下各 t 的前缀出现次数. 但这里数据有点变态, 题目保证了答案在 32 位有符号整数范围内, 但实际开到 64 位也会超精度的, 用 unsigned 反而过了.

实现

class Solution {
public:
int numDistinct(string s, string t) {
if (t.size() > s.size()) return 0;
int n = t.size();
vector<unsigned> f(n + 1);
f[0] = 1;
for (const auto& ch : s) {
for (int i = n; i > 0; i--) {
if (ch == t[i - 1]) f[i] += f[i - 1];
}
}
return f.back();
}
};

力扣每日一题940-不同的子序列II

日期:2026-09-07

题意

给定字符串 s, 求问其中不同的子序列各数.

思路

那应该是做一个 dp, 维护以各字符为结尾的子序列的个数.

实现

class Solution {
using ll = long long;
static constexpr int mod = 1e9 + 7;
public:
int distinctSubseqII(string s) {
array<ll, 26> f;
f.fill(0);
for (auto& ch : s) {
f[ch - 'a'] = (accumulate(f.begin(), f.end(), 0ll) + 1) % mod;
}
return accumulate(f.begin(), f.end(), 0ll) % mod;
}
};

力扣每日一题3870-统计范围内的逗号

日期:2026-09-08

题意

[1, n] 范围内的所有数在标准数学书写格式中, 会出现多少个 ‘,’.

思路

注意到数据范围为 1 <= n <= 1e5, 那显然只有大于等于一千的数有一个逗号.

实现

class Solution {
public:
int countCommas(int n) {
return max(0, n - 999);
}
};

力扣每日一题3871-统计范围内的逗号II

日期:2026-09-09

题意

[1, n] 范围内的所有数在标准数学书写格式中, 会出现多少个 ‘,’.

思路

和昨天一样的题意, 只是数据范围进行了扩大; 那么分阶段的统计贡献就好.

实现

class Solution {
using ll = long long;
public:
ll countCommas(ll n) {
ll ans = 0;
for (ll p = 1000; p <= n; p *= 1000) {
ans += max(0ll, n - p + 1);
if (p * 1000 > n) break;
}
return ans;
}
};

力扣每日一题2265-统计值等于子树平均值的节点数

日期:2026-09-10

题意

给定一棵二叉树, 求问节点值等于其子树节点平均值的点个数.

思路

那进行一个递归, 返回子树中的总权值和与点个数, 求符合条件的点数即可.

实现

/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int averageOfSubtree(TreeNode* root) {
int ans = 0;

auto dfs = [&](this auto&& self, TreeNode* u) -> array<int, 2> {
if (u == nullptr) return {0, 0};
auto [val1, cnt1] = self(u->left);
auto [val2, cnt2] = self(u->right);
int val = val1 + val2 + u->val, cnt = cnt1 + cnt2 + 1;
if (u->val == val / cnt) ans++;
return {val, cnt};
};
dfs(root);

return ans;
}
};

力扣每日一题3483-不同三位偶数的数目

日期:2026-09-11

题意

给定个位数数组 digits, 问其中能组成的不同三位数的偶数的数量.

思路

想来半天好像都有点不太好写, 一看发现数据范围非常小, 于是写了个暴力用运行时间换思考时间了.

实现

class Solution {
public:
int totalNumbers(vector<int>& digits) {
unordered_set<int> ust;
int n = digits.size();
for (int i = 0; i < n; i++) {
if (digits[i] == 0) continue;
for (int j = 0; j < n; j++) {
if (i == j) continue;
for (int k = 0; k < n; k++) {
if (k == i || k == j || (digits[k] & 1)) continue;
ust.insert(digits[i] * 100 + digits[j] * 10 + digits[k]);
}
}
}
return ust.size();
}
};