Q1 循环移位后的矩阵相似检查
-
解题思路:
- 就硬模拟吧 然后判断循环移位后的矩阵和之前是否相同
-
解题代码:
class Solution {
public:
bool areSimilar(vector<vector<int>>& mat, int k) {
int m = mat.size();
int n = mat[0].size();
k %= n;
auto reverse = [&](int i, int l, int r)
{
while(l <= r)
{
swap(mat[i][l], mat[i][r]);
l += 1;
r -= 1;
}
};
for(int i = 0; i < m; i++)
{
vector<int> src = mat[i];
reverse(i, 0, n-1);
if(i & 1)
{
reverse(i, 0, k-1);
reverse(i, k, n-1);
}
else
{
reverse(i, n-k, n-1);
reverse(i, 0, n-k-1);
}
if(src != mat[i])
return false;
}
return true;
}
};
- 更简洁的写法,不需要实际移动,只需要判断对应元素是否相同
class Solution {
public:
bool areSimilar(vector<vector<int>>& mat, int k) {
int n = mat[0].size();
k %= n;
if(k == 0)
return true;
for(auto &line : mat)
{
for(int j = 0; j < n; j++)
{
if(line[j] != line[(j+k) % n])
return false;
}
}
return true;
}
};
Q2 统计美丽子字符串I
-
解题思路:
- 该题可以用暴力的方法来做
- 直接去枚举每个子字符串,判断是否满足条件即可
-
解题代码:
class Solution {
public:
int beautifulSubstrings(string s, int k) {
int n = s.size();
int ans = 0;
for(int i = 0; i < n; i++)
{
int vowels = 0, consonants = 0;
for(int j = i; j < n; j++)
{
if(s[j] == 'a' || s[j] == 'e' || s[j] == 'i' || s[j] == 'o' || s[j] == 'u')
vowels += 1;
else
consonants += 1;
if(vowels == consonants && (vowels * consonants) % k == 0)
ans += 1;
}
}
return ans;
}
};
Q3 交换得到字典序最小的数组
-
解题思路:
- 首先将nums连带下标一起进行排序
- 根据nums[j] - nums[i] <= limit这个条件,将原数组分成多个部分
- 统计每个部分内的下标,将每部分内较小的数放在较小的下标
-
解题代码:
class Solution {
public:
vector<int> lexicographicallySmallestArray(vector<int>& nums, int limit) {
int n = nums.size();
vector<int> ans(n);
vector<pair<int, int>> items;
for(int i = 0; i < n; i++)
items.push_back({nums[i], i});
sort(items.begin(), items.end(), [](const pair<int, int>& a, const pair<int, int>& b)
{
return a.first < b.first;
});
auto func = [&](int l, int r)
{
priority_queue<int, vector<int>, greater<int>> pq;
for(int i = l; i <= r; i++)
pq.push(items[i].second);
int idx = l;
while(!pq.empty())
{
int cur = pq.top();
pq.pop();
ans[cur] = items[idx].first;
idx += 1;
}
};
for(int i = 0; i < n; i++)
{
int j = i + 1;
while(j < n && items[j].first - items[j-1].first <= limit)
j += 1;
func(i, j-1);
i = j-1;
}
return ans;
}
};
Q4 统计美丽子字符串II
- 题目链接
- 解题思路:
-
设字串长度为L,需要满足 L^2 是 4k的倍数
- (L/2)^2 % k = 0 => (L/2)^2 = mk => L^2 = 4mk => L^2 % (4k) = 0
- 找满足条件的最小L
- 假设最小L = k’,那么子字符串的长度L应该满足L % k’ = 0
-
元音字母个数 = 辅音字母个数
- 元音字母 = 1, 辅音字母 = -1
- 子数组元素和等于0即可满足条件
-
前缀和处理子数组元素和
- [j, i) = sum[i] - sum[j] = 0
- 需要满足sum[i] = sum[j]
- 同时需要满足(i - j) % k’ = 0 => i % k’ = j % k’
-
哈希表统计(i%k’, sum[i])的出现次数
-
class Solution {
public:
long long beautifulSubstrings(string s, int k) {
int d = 1;
while(1)
{
if(d * d % (4 * k) == 0)
{
k = d;
break;
}
d += 1;
}
int n = s.size();
vector<int> nums(n);
for(int i = 0; i < n; i++)
{
if(s[i] == 'a' || s[i] == 'e' || s[i] == 'i' || s[i] == 'o' || s[i] == 'u')
nums[i] = 1;
else
nums[i] = -1;
}
vector<int> sum(n+1, 0);
for(int i = 1; i <= n; i++)
sum[i] = sum[i-1] + nums[i-1];
map<pair<int, int>, int> m;
long long ans = 0;
for(int i = 0; i <= n; i++)
{
ans += m[{i%k, sum[i]}];
m[{i%k, sum[i]}] += 1;
}
return ans;
}
};