Q1 找出满足差值条件的下标I
-
解题思路:
- 数据范围很小,可以直接枚举两个下标,计算是否满足条件,如果满足条件直接返回对应下标
- 如果检查了所有下标都不满足条件,返回[-1,-1]
-
解题代码:
class Solution {
public:
vector<int> findIndices(vector<int>& nums, int indexDifference, int valueDifference) {
int n = nums.size();
for(int i = 0; i < n; i++)
{
for(int j = i; j < n; j++)
{
if(abs(i - j) >= indexDifference && abs(nums[i] - nums[j]) >= valueDifference)
return {i, j};
}
}
return {-1, -1};
}
};
Q2 最短且字典序最小的美丽子字符串
-
解题思路:
- 数据范围仍然很小
- 可以直接O(n^2)复杂度暴力枚举所有子字符串,判断其是否为最短的且字典序最小的美丽子字符串
-
解题代码
class Solution {
public:
string shortestBeautifulSubstring(string s, int k) {
int n = s.size();
string ans;
int ansLen = INT_MAX;
for(int i = 0; i < n; i++)
{
int cnt = 0;
string temp;
for(int j = i; j < n; j++)
{
if(s[j] == '1')
cnt += 1;
temp += s[j];
if(cnt == k)
{
if(temp.size() < ansLen || (temp.size() == ansLen && temp < ans))
{
ans = temp;
ansLen = temp.size();
}
break;
}
}
}
return ans;
}
};
-
解题思路2:
- 可以用滑动窗口
- 窗口中始终维护包含k个1的子字符串
- 右指针一直右移,当窗口中1的个数大于k或左指针指向0时,左指针右移
-
解题代码:
class Solution {
public:
string shortestBeautifulSubstring(string s, int k) {
int cnt = 0;
for(auto ch : s)
cnt += (ch == '1');
if(cnt < k)
return "";
string ans = s;
int n = s.size();
int l = 0;
int cnt1 = 0;
for(int r = 0; r < n; r++)
{
cnt1 += (s[r] == '1');
while(cnt1 > k || s[l] == '0')
{
cnt1 -= (s[l] == '1');
l += 1;
}
if(cnt1 == k)
{
string temp = s.substr(l, r-l+1);
if(temp.size() < ans.size() || temp.size() == ans.size() && temp < ans)
ans = temp;
}
}
return ans;
}
};
Q3 找出满足差值条件的下标II
-
解题思路:
- 从前向后遍历每一个下标
- 维护[0, max(0, i-indexDifference)]范围内的最大值、最小值及其下标
- 如果存在abs(最大值 - nums[i]) 或 abs(最小值 - nums[i]) 大于等于valueDifference,返回对应下标
- 如果不存在满足条件的下标,返回[-1, -1]
-
解题代码:
class Solution {
public:
vector<int> findIndices(vector<int>& nums, int indexDifference, int valueDifference) {
int mx = INT_MIN, mn = INT_MAX;
int mxIdx = -1, mnIdx = -1;
int n = nums.size();
for(int i = indexDifference; i < n; i++)
{
if(nums[i-indexDifference] > mx)
{
mx = nums[i-indexDifference];
mxIdx = i - indexDifference;
}
if(nums[i-indexDifference] < mn)
{
mn = nums[i-indexDifference];
mnIdx = i - indexDifference;
}
if(abs(mx - nums[i]) >= valueDifference)
return {mxIdx, i};
if(abs(mn - nums[i]) >= valueDifference)
return {mnIdx, i};
}
return {-1, -1};
}
};
赛后复盘可以只维护最大值和最小值的下标,不用同时维护最大值和最小值
Q4 前后缀分解
-
解题思路:
- 将二维数组展成一维矩阵
- 问题就变成了求每一个位置前缀与后缀的乘积
- 前后缀分解即可
-
解题代码:
class Solution {
public:
vector<vector<int>> constructProductMatrix(vector<vector<int>>& grid) {
int n = grid.size();
int m = grid[0].size();
vector<long long> left(n*m, 1), right(n*m, 1);
for(int i = 1; i < n*m; i++)
{
int x = (i-1) / m;
int y = (i-1) % m;
left[i] = (left[i-1] * grid[x][y]) % 12345;
}
for(int i = n*m-2; i >= 0; i--)
{
int x = (i+1) / m;
int y = (i+1) % m;
right[i] = (right[i+1] * grid[x][y]) % 12345;
}
vector<vector<int>> ans(n, vector<int>(m, 0));
for(int i = 0; i < n*m; i++)
{
int x = i / m;
int y = i % m;
ans[x][y] = (left[i] * right[i]) % 12345;
}
return ans;
}
};