5394. 对角线遍历 II
class Solution {
public:
vector<int> findDiagonalOrder(vector<vector<int>>& nums) {
vector<int> res;
vector<vector<int>> temp;
for(int i = 0; i < nums.size(); i++){
for(int j = 0; j < nums[i].size(); j++){
temp.push_back({i, j, nums[i][j]});
}
}
sort(temp.begin(), temp.end(), cmp);
for(int i = 0; i < temp.size(); i++){
res.push_back(temp[i][2]); // nums[i][j]的值
}
return res;
}
// cmp()函数的返回值要是bool,核心要义也是比较,我是这么理解的,因为sort默认是从小到大,所以在cmp如果还是要从小到大,那就a < b,返回值bool为true,不改变;而如果想要从大到小排,那么就要return a > b,因为默认a小于b,所以此时返回的bool就是false,要改变排序。
static bool cmp(vector<int>& v1, vector<int>& v2){
int v11 = v1[0], v12 = v1[1];
int v21 = v2[0], v22 = v2[1]; // i, j 坐标
// 横纵坐标之和从小到大排列
// 之和相同时,按照横坐标从大到小排列即是结果
if(v11+v12 < v21+v22){
return true; // 从小到大排序 true
}else if(v11+v12 > v21+v22){
return false;
}else{
return v11 > v21;// 从大到小
}
}
};
5392. 分割字符串的最大得分
class Solution {
public:
int maxScore(string s) {
int res = 0, conut1 = 0, count0 = 0;
for(int i = 0; i < s.length(); i++){
conut1 += s[i] - '0'; //统计1
}
for(int i = 0; i < s.length() - 1; i++){
if(s[i] - '0' == 0){// 0
count0++;
}else{
conut1--;
}
res = max(res, count0 + conut1);
}
return res;
}
};
5393. 可获得的最大点数
class Solution {
public:
int maxScore(vector<int>& cardPoints, int k) {
int sum = 0;
for(int i = 0 ;i < k; i++){
sum += cardPoints[i];
}
int res = sum;
int left = cardPoints.size() - 1;
for(int i = k - 1; i >= 0; i--){
sum = sum - cardPoints[i] + cardPoints[left];
left--;
res = max(sum, res);
}
return res;
}
};
双向队列
239. 滑动窗口最大值
思路参考视频(讲的挺不错的)
https://www.bilibili.com/video/BV1YV411o7Gr/
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
int size = nums.size();
if(size == 0){
return nums;
}
deque<int> window; // 存放下标index
vector<int> res;
// 头尾尾头
for(int i = 0; i < size;i++){
// 清除头部,保证队列长度
if(!window.empty() && window.front() < (i-k+1)){ // 队列头部元素index值 小于 i-k+1
window.pop_front();
}
// 尾部:把不符合的全部删除
while(!window.empty() && nums[i] >= nums[window.back()]){
window.pop_back();
}
// 尾部:当前元素入队 队列向右扩充
window.push_back(i);
// 头部:从头部返回最大值
if(i >= k - 1){ //
res.push_back(nums[window.front()]);
}
}
return res;
}
};
5180. 带限制的子序列和
动态规划+滑动窗口
class Solution {
public:
int constrainedSubsetSum(vector<int>& nums, int k) {
// 动态规划+滑动窗口
int size = nums.size();
vector<int> dp(size, 0); //dp[i]表示以i数字结尾的最大子序列
dp[0] = nums[0];
int ans = dp[0];
deque<int> window; // 前k个值的大小顺序,从而直接获取前k个最大的值,第i个数的前k个最大子序列和的单调递减栈
window.push_back(0);
for(int i = 1; i < size; i++){
dp[i] = max(dp[window.front()] + nums[i], nums[i]);// 转移方程
ans = max(ans, dp[i]);
//调整窗口大小,头
if(i - window.front() == k){
window.pop_front();
}
//调整队列内部,尾
while(!window.empty() && dp[window.back()] < dp[i]){
window.pop_back();
}
//尾,将结果放入进去,扩大窗口大小
window.push_back(i);
// 头 这里省略这一步
}
return ans;
}
};