2946. 循环移位后的矩阵相似检查
右移左移都是k位 所以只需要判断当前 i 位与 i+k 位是否一致 如果有一处不一致 则返回false 反之返回true
class Solution {
public:
bool areSimilar(vector<vector<int>>& mat, int k) {
int n = mat.size();
int m = mat[0].size();
for (int i = 0; i < n; i ++ )
for (int j = 0; j < m; j ++ )
if (mat[i][j] != mat[i][(j + k) % m]) return false;
return true;
}
};
2947. 统计美丽子字符串 I
这题最开始我想的是用前缀和+哈希表来做 写到一半发现好麻烦 最后还是选择用双指针来做...
将字符串从前往后遍历 同时记录元音字符和辅音字符数量 最后直接判断当前元音字符数量和辅音字符数量是否满足条件 满足则答案++
class Solution {
public:
int beautifulSubstrings(string s, int k) {
int res = 0;
for(int i = 0; i < s.size(); i++){
int vosum = 0, consum = 0;
for(int j = i; j < s.size(); j ++ ){
if(s[j]=='a'||s[j]=='e'||s[j]=='i'||s[j]=='o'||s[j]=='u') vosum ++;
else consum++ ;
if((vosum * consum) % k == 0 && vosum == consum) res ++;
}
}
return res;
}
};
2948. 交换得到字典序最小的数组
解法不唯一 在这里写两种
多路并归+二分
先将数组排序 排序后的数组记为temp 然后将数组分为不同的组 用一个下标数组分别指向不同组的最小值的下标 遍历nums数组 用两次二分找到当前数所在的组 数组c记录了该组中的最小值下标的增量 最后就可以通过idx和c数组从temp数组中找到对应的值写入答案中
class Solution {
public:
vector<int> lexicographicallySmallestArray(vector<int>& nums, int limit) {
int n = nums.size();
vector<int> temp = nums;
sort(temp.begin(), temp.end());
vector<int> idx;
idx.push_back(0);
for(int i = 1; i < n; i++ ){
if(abs(temp[i] - temp[i - 1]) > limit){
idx.push_back(i);
}
}
int m = idx.size();
vector<int> c(m,0);
for(int i = 0; i < n; i++ ){
//两次二分找到nums[i]所在的组
int j = upper_bound(temp.begin(), temp.end(), nums[i]) - temp.begin();
int k = lower_bound(idx.begin(), idx.end(), j) - idx.begin();
nums[i] = temp[idx[k - 1] + c[k - 1]];
//当前组的最小值下标往后移一位
c[k - 1]++;
}
return nums;
}
};
并查集+分组排序
先将数组排序 排序后的数组记为temp 然后将数组用并查集分为不同的组 用哈希表(数组)来映射到原数组的下标 最后将不同的组进行排序写入答案。
class Solution {
public:
vector<int> lexicographicallySmallestArray(vector<int>& nums, int limit) {
int n = nums.size();
UnionFind uf(n);
vector<pair<int, int>> a;
for(int i = 0; i < n; i++ ){
a.push_back({nums[i], i});
}
sort(a.begin(), a.end());
// 用并查集来进行分组
for(int i = 1; i < n; i++ ){
if(a[i].first - a[i-1].first <= limit){
uf.Union(a[i-1].second, a[i].second);
}
}
// 用哈希表(数组)来映射到原数组的下标
vector<vector<int>> groups(n);
for(int i = 0; i < n; i++ ){
int key = uf.Find(i);
groups[key].push_back(i);
}
// 对每个组的元素进行排序并替换回原始数组
for(int i = 0; i < n; i++ ){
if(groups[i].empty()){
continue;
}
int key = uf.Find(i);
vector<int> temp2;
for(int x : groups[i]){
temp2.push_back(nums[x]);
}
sort(temp2.begin(), temp2.end());
int j = 0;
for(int x : groups[i]){
nums[x] = temp2[j ++];
}
}
return nums;
}
};
2949. 统计美丽子字符串 II
最后一题有思路 没写出来
补题解
分解质因子+前缀和+哈希表
class Solution {
int p_sqrt(int n) {
int res = 1;
for (int i = 2; i * i <= n; i++) {
int i2 = i * i;
while (n % i2 == 0) {
res *= i;
n /= i2;
}
if (n % i == 0) {
res *= i;
n /= i;
}
}
if (n > 1) {
res *= n;
}
return res;
}
const int AEIOU_MASK = 1065233;
public:
long long beautifulSubstrings(string s, int k) {
k = p_sqrt(k * 4);
// 把 pair 压缩成 long long(或者 int)就可以用 umap 了
map<pair<int, int>, int> cnt;
cnt[{k - 1, 0}]++; // 添加 (k-1, sum)
long long ans = 0;
int sum = 0;
for (int i = 0; i < s.length(); i++) {
int bit = (AEIOU_MASK >> (s[i] - 'a')) & 1;
sum += bit * 2 - 1; // 1 -> 1 0 -> -1
ans += cnt[{i % k, sum}]++;
}
return ans;
}
};