1 5750. 人口最多的年份
class Solution {
public:
int maximumPopulation(vector<vector<int>>& logs) {
int n = logs.size();
int res = 1950, tmax = 0;
for(int i = 1950; i <= 2050; i++)
{
int sum = 0;
for(int j = 0; j < n; j++)
{
int l = logs[j][0], r = logs[j][1];
if(i >= l && i < r)
sum ++;
}
if(sum > tmax)
{
tmax = sum;
res = i;
}
}
return res;
}
};
2 5751. 下标对中的最大距离
思路:双指针:两个指针i,j分别指向nums1和nums2的末尾,当i指针向左移动时j不动或向左移动。
class Solution {
public:
int maxDistance(vector<int>& nums1, vector<int>& nums2) {
int n = nums1.size(), m = nums2.size();
int res = 0;
for(int i = n - 1, j = m - 1; i >= 0 && j >= 0; i--)
{
while(j >= i && nums2[j] < nums1[i])j--;
if(j >= i)res = max(res, j - i);
}
return res;
}
};
3 5752. 子数组最小乘积的最大值
类似于求最大子矩阵那道题
思路:
- 可以把它看做是求子矩阵面积,高为最小值,宽为数组元素之和。
- 遍历所有元素,若当前元素为矩阵的高,则其宽度为左边第1个小于它的元素到右边第1个大于它的元素构成的区间(开区间)内所有元素之和。(边界值特殊处理)
- 预处理出前缀和数组,利用单调递增栈,当即将入栈的元素大于栈顶,此时将栈顶作为高。用其构成的矩阵来更新答案。具体细节看代码
typedef unsigned long long ULL;
class Solution {
public:
int maxSumMinProduct(vector<int>& nums) {
int n = nums.size();
stack<int>stk;
vector<ULL>s(n + 1, 0);
const int mod = 1e9 + 7;
for(int i = 0; i < n; i++)s[i + 1] = s[i] + nums[i];
nums.push_back(-1);
ULL res = 0;
for(int i = 0; i <= n; i++)
{
while(!stk.empty() && nums[i] < nums[stk.top()])
{
ULL h = nums[stk.top()];
stk.pop();
if(stk.empty())res = max(res, h * s[i - 1 + 1]);
else res = max(res, h * (s[i - 1 + 1] - s[stk.top() + 1 + 1 - 1]));
}
stk.push(i);
}
return res % mod;
}
};
4 5753. 有向图中最大颜色值
参考
PS:之前想到往树形DP的方向做,不过没有时间了~
思路:
- 若拓扑排序后节点个数小于n,则有环(环中所有节点无法将入度减为0)
- 对于任意一条路径,在拓扑排序后前驱节点一定排在后继节点前面。
- DP:设f[u,c]为终点为u,颜色c的节点数量最多的路径,属性值为节点c的数量,有f[u,c] = max(f[pre1][c],f[pre2][c],…f[prek][c]) + (colors[u]==c)。即选取所有前驱节点中颜色c节点最多的路径来更新当前节点的值。
- 可以在拓扑排序的过程中用前驱节点更新其所有后继节点(当轮到该后继节点时,它已经被自己的所有前驱节点更新过了)。
class Solution {
public:
int largestPathValue(string colors, vector<vector<int>>& edges) {
int n = colors.size();
int m = edges.size();
vector<vector<int>>g(n);
vector<int>ru(n, 0);//入度
for(int i = 0; i < m; i++)//建立邻接表
{
int a = edges[i][0], b = edges[i][1];
g[a].push_back(b);
ru[b]++;
}
queue<int>q;
int cnt = 0;//已排序节点
for(int i = 0; i < n; i++)//入度为0进队列
if(ru[i] == 0)
q.push(i);
vector<vector<int> >f(n, vector<int>(26, 0));
while(q.size())//拓扑排序
{
int t = q.front();
q.pop();
cnt++;
f[t][colors[t] - 'a']++;
for(int i = 0; i < g[t].size(); i++)//更新所有后继节点f[][]和入度
{
int j = g[t][i];
for(int k = 0; k < 26; k++)
f[j][k] = max(f[j][k], f[t][k]);
if(--ru[j] == 0)//入度为0进队列
q.push(j);
}
}
if(cnt < n)return -1;//有环
int res = 0;//选出最大
for(int i = 0; i < n; i++)
for(int j = 0; j < 26; j++)
res = max(res, f[i][j]);
return res;
}
};