909. 蛇梯棋 - 力扣(LeetCode)
timer:2025-5-31
class Solution {
public:
int snakesAndLadders(vector<vector<int>>& board) {
int n = board.size();
vector<int8_t> vis(n * n + 1); // 记录每个位置是否被访问过
vis[1] = true; // 起点标记为已访问
vector<int> q; // BFS队列
q.push_back(1); // 从位置1开始
// BFS主循环,i表示当前步数
for(int i = 0; !q.empty(); i++){
auto t = q; // 保存当前层的所有位置
q.clear(); // 清空队列准备下一层
// 遍历当前层的所有位置
for(auto& x : t){
if(x == n * n){ // 到达终点
return i;
}
// 模拟掷骰子,枚举所有可能的下一步位置
for(int y = x + 1; y <= min(x + 6, n * n); y++){
// 将一维位置y转换为二维棋盘坐标
int r = (y - 1) / n, c = (y - 1) % n;
if(r % 2) // 奇数行需要镜像列坐标(注意这里的奇偶行指的是数组的奇偶行,也就是从最上方开始为第0行)
c = n - c - 1;
// 获取棋盘上该位置的值
int nex = board[n - 1 - r][c];
if(nex == -1) // 没有梯子或蛇
nex = y;
// 如果下一步位置未被访问过
if(!vis[nex]){
q.push_back(nex); // 加入队列
vis[nex] = true; // 标记为已访问
}
}
}
}
return -1; // 无法到达终点
}
};
2025-6:
2929. 给小朋友们分糖果 II - 力扣(LeetCode)
timer:2025-6-1
class Solution {
// 计算组合数C(n,2) = n*(n-1)/2
long long C2(long long n) {
return n > 1 ? n * (n - 1) / 2 : 0;
}
public:
/*
* 计算将n个无区别糖果放入3个有区别盒子的合法分配方案数
* 每个盒子最多放limit个糖果
*
* 容斥原理应用:
* 总方案数(允许空盒) = C(n+2,2) (隔板法)
* 设Ai表示第i个盒子超过limit的方案集合
* 需要计算 |A1∪A2∪A3| 并从总方案中扣除
*
* 根据容斥公式:
* |A1∪A2∪A3| = Σ|Ai| - Σ|Ai∩Aj| + |A1∩A2∩A3|
*
* 单集合大小:|Ai| = C(n - limit, 2) (共3个)
* 双集合交集:|Ai∩Aj| = C(n - 2*limit - 1, 2) (共3个)
* 三集合交集:|A1∩A2∩A3| = C(n - 3*limit - 2, 2) (若存在)
*/
long long distributeCandies(int n, int limit) {
return C2(n + 2) // 总方案数
- 3 * C2(n - limit + 1) // 减去单集合
+ 3 * C2(n - 2 * limit) // 加上双集合交集
- C2(n - 3 * limit - 1); // 减去三集合交集
}
};
135. 分发糖果 - 力扣(LeetCode)
timer:2025-6-2
class Solution {
public:
int candy(vector<int>& ratings) {
int n = ratings.size();
if (n == 0) return 0;
// 初始化每个孩子至少有一个糖果
vector<int> candies(n, 1);
// 第一次遍历:从左到右,确保右边评分高的孩子比左边的多
for (int i = 1; i < n; i++) {
if (ratings[i] > ratings[i-1]) {
candies[i] = candies[i-1] + 1;
}
}
// 第二次遍历:从右到左,确保左边评分高的孩子比右边的多
for (int i = n-2; i >= 0; i--) {
if (ratings[i] > ratings[i+1]) {
candies[i] = max(candies[i], candies[i+1] + 1);
}
}
// 计算总糖果数
int total = 0;
for (int num : candies) {
total += num;
}
return total;
}
};
1298. 你能从盒子里获得的最大糖果数 - 力扣(LeetCode)
timer:2025-6-3
// DFS
// 记录状态
// 1、找到钥匙(状态0也表示为有钥匙)
// 2、找到箱子
// 3、当钥匙和箱子都找到我们就能拿到糖果
class Solution {
public:
int maxCandies(vector<int>& status, vector<int>& candies, vector<vector<int>>& keys, vector<vector<int>>& containedBoxes, vector<int>& initialBoxes) {
auto& has_key = status;
vector<uint8_t> has_box(status.size());
// 标记已知箱
for(auto& x : initialBoxes)
has_box[x] = true;
int ans = 0;
// 开箱函数
auto dfs = [&](this auto&& dfs, int x) -> void {
ans += candies[x]; // 拿糖
has_box[x] = false;
// 拿到钥匙
for(int y : keys[x]){
has_key[y] = true;
if(has_box[y]) // 有钥匙对应的箱子
dfs(y);
}
// 拿到箱子
for(int y : containedBoxes[x]){
has_box[y] = true;
if(has_key[y]) // 有箱子对应的钥匙
dfs(y);
}
};
// 开始开箱
for(auto& x : initialBoxes)
if(has_box[x] && has_key[x])
dfs(x);
return ans;
}
};
3403. 从盒子中找出字典序最大的字符串 I - 力扣(LeetCode)
timer: 2025-6-4
一:枚举子串左端点
// 枚举子串左端点解法
class Solution {
public:
string answerString(string word, int numFriends) {
int n = word.size();
string ans = "";
// 特殊情况:当每个朋友恰好分到1个字符时,整个字符串即为答案
if(numFriends == 1)
return word;
// 枚举所有可能的子串左端点i
for(int i = 0; i < n; i++){
// 计算从i开始的有效子串长度(受numFriends限制)
// 子串长度至少为1,且不能超过原字符串长度
int len = n - max((numFriends - 1), i);
if(len <= 0) continue; // 跳过无效长度
// 更新最大字典序子串
ans = max(ans, word.substr(i, len));
}
return ans;
}
};
二: 计算字典序最大的后缀
// 双指针优化解法:线性时间复杂度
class Solution {
public:
string answerString(string word, int numFriends) {
// 特殊情况处理
if (numFriends == 1) {
return word;
}
int n = word.size();
int i = 0; // 当前最大字典序子串的起始位置
int j = 1; // 探索指针,尝试寻找更大的子串
while (j < n) {
int len = 0; // 公共前缀长度
// 计算i和j开始的子串的最长公共前缀
while (j + len < n && word[i + len] == word[j + len]) {
len++;
}
// 如果j位置子串在公共前缀后更大,则更新i
if (j + len < n && word[i + len] < word[j + len]) {
int t = i; // 保存旧的i值
i = j; // 更新i为新的更大子串起始位置
// 优化j的下一个位置:跳过已知不可能的起始点
j = max(j + 1, t + len + 1);
} else {
// 否则直接跳过公共前缀长度+1的距离
j += len + 1;
}
}
// 计算最终子串长度(受numFriends限制)
// 确保子串长度至少为1,且不超过原字符串长度
int len = n - max(numFriends - 1, i);
return word.substr(i, len);
}
};
1061. 按字典序排列最小的等效字符串 - 力扣(LeetCode)
timer:2025-6-5
class Solution {
public:
string smallestEquivalentString(string s1, string s2, string baseStr) {
// 初始化并查集数组:parent[x] 表示字符 x 的父节点,初始时每个节点的父节点是自身
int parent[26];
for (int i = 0; i < 26; ++i) {
parent[i] = i;
}
// 查找字符 x 所在集合的根节点(带路径压缩)
function<int(int)> findRoot = [&](int x) {
if (parent[x] != x) {
parent[x] = findRoot(parent[x]); // 路径压缩:直接将节点连接到根节点
}
return parent[x];
};
// 合并两个字符所在的集合,确保每个集合的根节点是字典序最小的字符
auto unionChars = [&](char c1, char c2) {
int root1 = findRoot(c1 - 'a');
int root2 = findRoot(c2 - 'a');
if (root1 != root2) {
// 让较大的根节点指向较小的根节点,确保每个集合的根是最小字符
if (root1 > root2) {
parent[root1] = root2;
} else {
parent[root2] = root1;
}
}
};
// 处理所有等价关系,建立字符间的连通性
for (int i = 0; i < s1.size(); ++i) {
unionChars(s1[i], s2[i]);
}
// 将 baseStr 中的每个字符替换为其等价类中的最小字符
for (char& c : baseStr) {
c = findRoot(c - 'a') + 'a';
}
return baseStr;
}
};
2434. 使用机器人打印字典序最小的字符串 - 力扣(LeetCode)
timer:2025-6-6
class Solution {
public:
string robotWithString(string s) {
int n = s.size();
// 预处理后缀最小值数组
// suf_min[i] 表示从索引i到字符串末尾的最小字符
vector<char> suf_min(n + 1);
suf_min[n] = 'z'; // 初始化边界值为最大字符'z'
for (int i = n - 1; i >= 0; i--) {
suf_min[i] = min(suf_min[i + 1], s[i]);
}
string ans; // 存储最终结果的字符串
stack<char> st; // 模拟机器人的栈操作
// 遍历输入字符串的每个字符
for (int i = 0; i < n; i++) {
st.push(s[i]); // 将当前字符压入栈
// 核心逻辑:如果栈顶字符小于等于剩余字符中的最小字符
// 则应该立即将其添加到结果中,确保字典序最小
while (!st.empty() && st.top() <= suf_min[i + 1]) {
ans += st.top();
st.pop();
}
}
return ans;
}
};
3423. 循环数组中相邻元素的最大差值 - 力扣(LeetCode)
timer: 2025-6-12
class Solution {
public:
int maxAdjacentDistance(vector<int>& nums) {
int n = nums.size();
int ans = abs(nums[n - 1] - nums[0]);
for(int i = 1; i < n; i++){
ans = max(abs(nums[i] - nums[i - 1]), ans);
}
return ans;
}
};
2566. 替换一个数字后的最大差值 - 力扣(LeetCode)
timer: 2025-6-14
// 简单贪心
// 最大值: 将最前面的数字替换为最大‘9’
// 最小值: 将最前面的数字替换为最小‘0’
// 注: 要注意全部替换
class Solution {
public:
int minMaxDifference(int num) {
string s = to_string(num);
// 替换成最大值
int mmax = num;
for (char ch : s) {
if (ch != '9') {
string tmp = s;
ranges::replace(tmp, ch, '9');
mmax = stoi(tmp);
break;
}
}
// 替换成最小值
int mmin;
char ch0 = s[0];
ranges::replace(s, ch0, '0');
mmin = stoi(s);
return mmax - mmin;
}
};
2016. 增量元素之间的最大差值 - 力扣(LeetCode)
timer: 2025-6-16
// 方法一:暴力枚举法
// 时间复杂度:O(n²),空间复杂度:O(1)
class Solution {
public:
int maximumDifference(vector<int>& nums) {
int n = nums.size(); // 获取数组长度
int ans = -1; // 初始化最大差值为-1(题目要求未找到正差值时返回-1)
// 外层循环遍历每个可能的起始元素
for(int i = 0; i < n; i++)
// 内层循环遍历每个可能的结束元素(需在起始元素之后)
for(int j = i + 1; j < n; j++)
// 若当前元素对满足正差值条件,则更新最大差值
if(nums[j] - nums[i] > 0)
ans = max(ans, nums[j] - nums[i]);
return ans; // 返回最大正差值,若不存在则返回-1
}
};
// 方法二:一次遍历优化法
// 时间复杂度:O(n),空间复杂度:O(1)
class Solution {
public:
int maximumDifference(vector<int>& nums) {
int n = nums.size(); // 获取数组长度
int ans = 0; // 初始化最大差值为0
int mmin = INT_MAX; // 初始化最小值为INT_MAX,用于跟踪已遍历元素中的最小值
// 一次遍历数组
for(int i = 0; i < n; i++){
// 计算当前元素与历史最小值的差值,并更新最大差值
ans = max(ans, nums[i] - mmin);
// 更新已遍历元素中的最小值
mmin = min(nums[i], mmin);
}
// 若最大差值为0,说明不存在正差值,返回-1;否则返回最大差值
return ans ? ans : -1;
}
};
1432. 改变一个整数能得到的最大差值 - 力扣(LeetCode)
timer: 2025-6-16
class Solution {
public:
int maxDiff(int num) {
// 将数字转换为字符串以便逐位处理
string s = to_string(num);
// 定义一个lambda函数用于替换字符串中的指定字符并转换回整数
// oldChar: 需要替换的字符
// newChar: 替换后的新字符
auto replace_num = [&](char oldChar, char newChar) {
int x = 0;
for (auto& ch : s) {
// 如果当前字符等于oldChar,则替换为newChar,否则保持不变
char c = ch == oldChar ? newChar : ch;
// 逐位构建新的整数值
x = x * 10 + (c - '0');
}
return x;
};
// 计算替换后能得到的最大数值
int mmax = num;
// 遍历字符串,找到第一个不是'9'的字符
for (char ch : s) {
if (ch != '9') {
// 将该字符替换为'9'以获得可能的最大值
mmax = replace_num(ch, '9');
break;
}
}
// 计算替换后能得到的最小数值
int mmin = num;
// 如果第一位不是'1',则将第一位替换为'1'
if (s[0] != '1') {
mmin = replace_num(s[0], '1');
} else {
// 否则从第二位开始寻找第一个大于'1'的字符
for (int i = 1; i < s.size(); i++) {
if (s[i] > '1') {
// 将该字符替换为'0'以获得可能的最小值
mmin = replace_num(s[i], '0');
break;
}
}
}
// 返回最大值和最小值的差值
return mmax - mmin;
}
};
3405. 统计恰好有 K 个相等相邻元素的数组数目 - 力扣(LeetCode)
timer: 2025-6-17
const int MOD = 1'000'000'007;
const int MX = 100'000;
typedef long long ll;
ll F[MX]; // 阶乘
ll INV_F[MX]; // 对应阶乘的逆元
// 快速幂
ll qpow(ll x, int n){
ll res = 1;
for(; n; n /= 2){
if(n % 2){
res = res * x % MOD;
}
x = x * x % MOD;
}
return res;
}
// 初始化阶乘
auto init = []{
F[0] = 1;
for(int i = 1; i < MX; i++)
F[i] = F[i - 1] * i % MOD;
INV_F[MX - 1] = qpow(F[MX - 1], MOD - 2);
for(int i = MX - 1; i > 0; i--){
INV_F[i - 1] = INV_F[i] * i % MOD;
}
return 0;
}();
// 计算组合
ll comb(int n, int m){
return F[n] * INV_F[m] % MOD * INV_F[n - m] % MOD;
}
class Solution {
public:
int countGoodArrays(int n, int m, int k) {
return comb(n - 1, k) * m % MOD * qpow(m - 1, n - k - 1) % MOD;
}
};
// 作者:灵茶山艾府
// 链接:https://leetcode.cn/problems/count-the-number-of-arrays-with-k-matching-adjacent-elements/solutions/3033292/chun-shu-xue-ti-pythonjavacgo-by-endless-mxj7/
// 来源:力扣(LeetCode)
// 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
2966. 划分数组并满足最大差限制 - 力扣(LeetCode)
timer:2025-6-18
class Solution {
public:
vector<vector<int>> divideArray(vector<int>& nums, int k) {
int n = nums.size();
sort(nums.begin(), nums.end());
vector<vector<int>> ans;
// 遍历每个分组,每组3个元素
for (int i = 0; i < n; i += 3) {
// 检查当前分组的最大值和最小值之差是否不超过k
if (nums[i+2] - nums[i] > k) {
return {};
}
// 将当前分组加入结果集
ans.push_back({nums[i], nums[i+1], nums[i+2]});
}
return ans;
}
};
2294. 划分数组使最大差为 K - 力扣(LeetCode)
timer:2025-6-19
class Solution {
public:
int partitionArray(vector<int>& nums, int k) {
int n = nums.size();
sort(nums.begin(), nums.end());
int pre = nums[0], ans = 1; // 要注意先排序在初始化pre
// if (n == 0) return 0;
for(int i = 1; i < n; i++){
if((nums[i] - pre) > k){
pre = nums[i];
ans++;
}
}
return ans;
}
};
3443. K 次修改后的最大曼哈顿距离 - 力扣(LeetCode)
timer: 2025-6-20
/*
* 方法一:曼哈顿距离最大化算法
*
* 坐标简化:
* - 向左(l) 向右(r) 向上(u) 向下(d)
*
* 曼哈顿距离公式:
* distance = |l - r| + |u - d|
*
* 优化目标:
* 通过修改方向字符,最大化 |l - r| 和 |u - d|
*
* 优化策略:
* 1. 每次修改可以将一个方向字符变为其相反方向(例如:E→W 或 N→S)
* 2. 每次修改可以使对应方向的计数变化量+2
* 3. 最优修改次数为 min(l, r, k) 或 min(u, d, k)
*
* 最终距离计算公式:
* distance = |l - r| + 2 * move
* distance = |u - d| + 2 * move
* 其中 move = min(同向计数, 反向计数, 剩余修改次数k)
*/
class Solution {
public:
int maxDistance(string s, int k) {
// 统计四个方向的总计数
int l = 0, r = 0, u = 0, d = 0;
int ans = 0;
// 遍历字符串逐步更新方向计数并计算最大可能距离
for (char ch : s) {
// 更新方向计数
if (ch == 'N') u++;
else if (ch == 'S') d++;
else if (ch == 'E') r++;
else l++;
// 剩余可用修改次数
int x = k;
// 计算单个轴向的最大可能距离
auto func = [&](int a, int b) -> int {
// 计算可转换的最大次数:受限于同向计数、反向计数和剩余修改次数
int move = min({a, b, x});
// 扣除已使用的修改次数
x -= move;
// 计算转换后的轴向距离:原始距离 + 2 * 转换次数
return abs(a - b) + 2 * move;
};
// 更新最大曼哈顿距离:x轴向距离 + y轴向距离
ans = max(ans, func(l, r) + func(u, d));
}
return ans;
}
};
// 方法二
class Solution {
public:
int maxDistance(string s, int k) {
int ans = 0; // 记录最大可能的曼哈顿距离
int x = 0, y = 0; // 当前位置的坐标,初始化为原点(0,0)
// 遍历字符串中的每个字符
for (int i = 0; i < s.size(); i++) {
// 根据字符更新当前位置
if (s[i] == 'N') y++; // 北:y坐标增加
else if (s[i] == 'S') y--; // 南:y坐标减少
else if (s[i] == 'E') x++; // 东:x坐标增加
else x--; // 西:x坐标减少
// 计算当前可能的最大曼哈顿距离
// abs(x) + abs(y):当前位置的曼哈顿距离
// k * 2:使用k次修改机会可能增加的最大距离(每次修改增加2个单位)
// i + 1:当前已处理的字符数,即最多可以修改的次数
// min(...):确保修改次数不超过可用次数
// max(ans, ...):更新最大距离
ans = max(ans, min(abs(x) + abs(y) + k * 2, i + 1));
}
return ans; // 返回最大可能的曼哈顿距离
}
};
3085. 成为 K 特殊字符串需要删除的最少字符数 - 力扣(LeetCode)
timer: 2025-6-21
// 方法一: 贪心枚举最小频率基准值
// 时间复杂度: O(n + 26²) ≈ O(n)
// 空间复杂度: O(26) ≈ O(1)
class Solution {
public:
int minimumDeletions(string word, int k) {
// 统计每个字符的出现次数
vector<int> count(26, 0);
for (char ch : word) {
count[ch - 'a']++;
}
// 按频率升序排序,便于贪心枚举基准值
sort(count.begin(), count.end());
int maxSave = 0; // 最多可保留的字符数
// 枚举所有可能的最小频率基准值 base = count[i]
// 即假设保留的字符中最少出现次数为 base
for (int i = 0; i < 26; i++) {
int base = count[i];
int sum = 0;
// 遍历所有频率 ≥ base 的字符(频率 < base 的字符已被自动排除)
for (int j = i; j < 26; j++) {
// 对于频率 ≥ base 的字符,保留其原始频率或 base + k 中的较小值
// 确保保留的字符频率不超过 base + k
sum += min(count[j], base + k);
}
// 更新最大保留字符数
maxSave = max(maxSave, sum);
}
// 总删除次数 = 原字符串长度 - 最多可保留的字符数
return word.size() - maxSave;
}
};
// 方法二: 滑动窗口优化
// 时间复杂度: O(n + 26 log 26) ≈ O(n)
// 空间复杂度: O(26) ≈ O(1)
class Solution {
public:
int minimumDeletions(string word, int k) {
// 统计每个字符的出现次数
vector<int> count(26, 0);
for (char ch : word) {
count[ch - 'a']++;
}
// 按频率升序排序,便于贪心枚举
sort(count.begin(), count.end());
int maxSave = 0; // 最多可保留的字符数
int windowSum = 0; // 当前窗口内字符的总出现次数
int right = 0; // 滑动窗口的右边界
// 枚举所有可能的最小频率值 base(贪心策略)
for (int base : count) {
// 扩展窗口右边界,直到窗口内所有字符的频率 ≤ base + k
// 这些字符可以完整保留(频率在 [base, base+k] 范围内)
while (right < 26 && count[right] <= base + k) {
windowSum += count[right];
right++;
}
// 计算当前方案的总保留字符数:
// 1. 窗口内的字符按原始频率保留(windowSum)
// 2. 窗口外的字符按最大可能保留(每个字符保留 base + k 个)
int currentSave = windowSum + (base + k) * (26 - right);
maxSave = max(maxSave, currentSave);
// 窗口左边界右移,移除当前基准值 base
// 为下一轮更大的 base 做准备
windowSum -= base;
}
// 总删除次数 = 原字符串长度 - 最多可保留的字符数
return word.size() - maxSave;
}
};
2138. 将字符串拆分为若干长度为 k 的组 - 力扣(LeetCode)
timer:2025-6-22
// class Solution {
// public:
// vector<string> divideString(string s, int k, char fill) {
// vector<string> ans;
// int l = 0, r = k - 1;
// while(s.size() % k){
// s += fill;
// }
// int n = s.size();
// int count = n / k;
// while(count--){
// string path = "";
// for(int i = l; i <= r; i++){
// path += s[i];
// }
// ans.push_back(path);
// l += k;
// r += k;
// }
// return ans;
// }
// };
class Solution {
public:
vector<string> divideString(string s, int k, char fill) {
vector<string> result;
int n = s.size();
// 计算需要填充的字符数
int padding = (k - (n % k)) % k;
// 一次性填充所有需要的字符
s.append(padding, fill);
// 遍历字符串,每次处理k个字符
for (int i = 0; i < s.size(); i += k) {
// 直接使用子字符串,避免逐个字符拼接
result.push_back(s.substr(i, k));
}
return result;
}
};
2081. k 镜像数字的和 - 力扣(LeetCode)
timer: 2025-6-23
// 存储各进制(2-9)下的k镜像数,ans[k]表示k进制下的k镜像数列表
vector<long long> ans[10];
// 每个进制需要收集的k镜像数的最大数量
const int mmax = 30;
/**
* 判断数字x在k进制下是否为回文数
* @param x 待判断的十进制数
* @param k 目标进制
* @return true表示x在k进制下是回文数,false表示不是
*/
bool isKthBasePalindrome(long long x, int k) {
// 排除k进制下有前导零的情况(若x能被k整除且x不为0,则k进制表示有前导零)
if (x % k == 0 && x != 0) {
return false;
}
// 反转k进制数字
long long rev = 0;
// 优化循环条件,减少不必要的计算
while (rev < x / k) {
rev = rev * k + x % k;
x /= k;
}
// 比较反转前后的数字,考虑数字长度为奇数的情况
return rev == x || rev == x / k;
}
/**
* 检查是否已为每个进制收集到足够数量的k镜像数
* @param x 待检查的十进制回文数
* @return true表示所有进制都已收集满mmax个k镜像数,false表示未收集满
*/
bool checkCountN(long long x) {
bool flag = true;
// 遍历2到9的所有进制
for (int k = 2; k <= 9; k++) {
// 如果当前进制收集的k镜像数未满且x在该进制下是回文数,则添加到列表
if (ans[k].size() < mmax && isKthBasePalindrome(x, k)) {
ans[k].push_back(x);
}
// 只要有一个进制未收集满,就继续收集
if (ans[k].size() < mmax) {
flag = false;
}
}
if (!flag) {
return false;
}
// 计算每个进制下k镜像数的前缀和(用于快速获取前n项和)
for (int k = 2; k <= 9; k++) {
partial_sum(ans[k].begin(), ans[k].end(), ans[k].begin());
}
return true;
}
// 全局初始化lambda表达式,程序启动时自动执行
auto init = []() {
// 按位数生成十进制回文数,base表示当前处理的位数的基数(1, 10, 100, ...)
for (int base = 1;; base *= 10) {
// 生成奇数位十进制回文数
for (int i = base; i < base * 10; i++) {
long long x = i;
// 通过反转前半部分生成奇数位回文数(如i=123,生成12321)
for (int j = i / 10; j > 0; j /= 10) {
x = x * 10 + j % 10;
}
// 检查该回文数是否为各进制的k镜像数
if (checkCountN(x)) {
return 0; // 所有进制收集满后退出初始化
}
}
// 生成偶数位十进制回文数
for (int i = base; i < base * 10; i++) {
long long x = i;
// 通过反转前半部分生成偶数位回文数(如i=1234,生成1234321)
for (int j = i; j > 0; j /= 10) {
x = x * 10 + j % 10;
}
// 检查该回文数是否为各进制的k镜像数
if (checkCountN(x)) {
return 0; // 所有进制收集满后退出初始化
}
}
}
}();
class Solution {
public:
/**
* 获取k进制下的第n个k镜像数
* @param k 目标进制(2-9)
* @param n 第n个k镜像数
* @return k进制下的第n个k镜像数(1-based索引)
*/
long long kMirror(int k, int n) {
return ans[k][n - 1]; // 转换为0-based索引获取结果
}
};
2200. 找出数组中的所有 K 近邻下标 - 力扣(LeetCode)
timer: 2025-6-24
class Solution {
public:
vector<int> findKDistantIndices(vector<int>& nums, int key, int k) {
vector<int> ans; // 存储结果的数组
// 初始化last为-k-1,确保当数组前k个元素中没有key时,last < i-k
// 这样可以正确处理数组起始部分的边界情况
int last = -k - 1;
// 初始化阶段:从k-1到0逆序查找第一个key的位置
// 目的是为数组的第一个窗口(索引0到k)设置正确的last值
for(int i = k - 1; i >= 0; i--){
if(nums[i] == key){
last = i; // 找到key后更新last为该索引
break; // 只需要最近的key,找到后立即退出循环
}
}
// 主循环:遍历数组中的每个元素
for(int i = 0; i < nums.size(); i++){
// 检查当前位置i的右侧k位置是否为key
// 如果是,则更新last为该位置,因为这是当前能找到的最近的key
if(i + k < nums.size() && nums[i + k] == key)
last = i + k;
// 判断条件:如果last >= i - k,表示在i的左侧或当前位置存在key
// 且该key与i的距离不超过k,因此i符合条件
if(last >= i - k)
ans.push_back(i);
}
return ans;
}
};