dfs|前后缀分解

lc1671

前后缀分解+最长递增子序列(子序列dp)

左右开弓 典中典

class Solution {

public:

int minimumMountainRemovals(vector<int>& nums) {

int n=nums.size();

vector<int> pre(n,INT_MAX),suf(n,INT_MAX);

for(int i=0;i<n;i++){

pre[i]=i;

for(int j=0;j<i;j++){

if(nums[i]>nums[j]){

pre[i]=min(pre[i],pre[j]+i-j-1);

}

}

}

for(int i=n-1;i>=0;i--){

suf[i]=n-i-1;

for(int j=n-1;j>i;j--){

if(nums[i]>nums[j]){

suf[i]=min(suf[i],suf[j]+j-i-1);

}

}

}

int ans=INT_MAX;

for(int i=1;i<n-1;i++){

if(pre[i]!=i&&suf[i]!=n-i-1) {

ans = min(ans, pre[i] + suf[i]);

}

}

return ans;

}

};

lis复用

class Solution {

public:

//误区:原数组的最大值不一定是答案的峰值

//定义dp[i]为以i结尾最长递增子序列长度

//维护数组pre[i],表示前i个元素的最长递增子序列长度,每次更新完dp[i]插入pre

//将数组反转后求递增子序列长度,即原数组的后缀递减子序列长度

//所以可以包装一个函数,调用两次求出pre和suf数组

//原数组的最长山型序列长度即为pre[i] + suf[n-1-i] - 1(因为第i个元素算了两次)

//枚举i统计最大值maxv,答案即为n - maxv

void LIS(vector<int>& nums,vector<int>& lis){

int n = nums.size();

vector<int> dp(n,1);

for(int i = 0;i < n;i++){

for(int j = i-1;j >= 0;j--){

if(nums[j] < nums[i]) dp[i] = max(dp[i],dp[j] + 1);

}

lis.push_back(dp[i]);

}

}

int minimumMountainRemovals(vector<int>& nums) {

int n = nums.size();

vector<int> pre,suf;

LIS(nums,pre);

reverse(nums.begin(),nums.end());

LIS(nums,suf);

int maxv = 0;

for(int i = 0;i < n;i++){ //注意这里pre、suf都要>1,否则峰值会出现在一端,不符合题意

if(pre[i] > 1 && suf[n - 1 - i] > 1){

maxv = max(maxv,pre[i] + suf[n - 1 - i] - 1);

}

}

return n - maxv;

}

};

优化

两次贪心+二分 分别计算每个位置的最长严格递增子序列(前缀)和最长严格递减子序列(后缀),找到最长山脉子序列的长度后,用数组总长度减去该长度,得到最少需要移除的元素数量

class Solution {

public:

int minimumMountainRemovals(vector<int> &nums) {

int n = nums.size();

vector<int> suf(n), g;

for (int i = n - 1; i; i--)

{

int x = nums[i];

auto it = lower_bound(g.begin(), g.end(), x);

suf[i] = it - g.begin() + 1; // 从 nums[i] 开始的最长严格递减子序列的长度

if (it == g.end())

g.push_back(x);

else

*it = x;

}

int mx = 0;

g.clear();

for (int i = 0; i < n - 1; i++) {

int x = nums[i];

auto it = lower_bound(g.begin(), g.end(), x);

int pre = it - g.begin() + 1; // 在 nums[i] 结束的最长严格递增子序列的长度

if (it == g.end()) {

g.push_back(x);

} else {

*it = x;

}

if (pre >= 2 && suf[i] >= 2) {

mx = max(mx, pre + suf[i] - 1); // 减去重复的 nums[i]

}

}

return n - mx;

}

};

lc1589

差分+前缀和+贪心

++cnt[start]++;++

cnt[end + 1]--;

for (int i = 1; i < n; i++)

cnt[i] += cnt[i - 1];

#include <vector>

#include <algorithm>

using namespace std;

const int MOD = 1e9 + 7;

class Solution {

public:

int maxSumRangeQuery(vector<int>& nums, vector<vector<int>>& requests)

{

int n = nums.size();

// 1. 差分 统计每个索引的查询次数

vector<int> cnt(n, 0);

for (auto& req : requests)

{

int start = req[0], end = req[1];

++cnt[start]++;++

if (end + 1 < n)

++cnt[end + 1]--;++

}

// 2. 前缀和,每个索引的实际查询次数

for (int i = 1; i < n; i++)

++cnt[i] += cnt[i - 1];++

// 3. 对nums和查询次数都降序排序

sort(nums.rbegin(), nums.rend());

sort(cnt.rbegin(), cnt.rend());

// 4. 计算总结果并取余

long long ret = 0;

for (int i = 0; i < n; i++)

ret = (ret + (long long)nums[i] * cnt[i]) % MOD;

return ret % MOD;

}

};

lc1339

两次递归遍历二叉树

先计算整棵树的节点值总和,再++遍历每个子树计算其节点值和++

找出子树和与剩余部分和的最大乘积

class Solution {

long long sum = 0, ret = 0;

const int MOD = 1e9 + 7;

public:

int maxProduct(TreeNode* root)

{

cal_sum(root);

dfs(root);

return ret % MOD;

}

void cal_sum(TreeNode* node)

{

if (!node) return;

sum += node->val;

cal_sum(node->left);

cal_sum(node->right);

}

long long dfs(TreeNode* node)

{

if (!node) return 0;

long long sub_sum = dfs(node->left) + dfs(node->right) + node->val;

long long p = sub_sum * (sum - sub_sum);

ret=max(ret,p);

return sub_sum;

}

};

相关推荐
啊森要自信3 小时前
CANN ops-cv:AI 硬件端视觉算法推理训练的算子性能调优与实战应用详解
人工智能·算法·cann
仟濹3 小时前
算法打卡day2 (2026-02-07 周五) | 算法: DFS | 3_卡码网99_计数孤岛_DFS
算法·深度优先
驭渊的小故事3 小时前
简单模板笔记
数据结构·笔记·算法
YuTaoShao3 小时前
【LeetCode 每日一题】1653. 使字符串平衡的最少删除次数——(解法一)前后缀分解
算法·leetcode·职场和发展
VT.馒头4 小时前
【力扣】2727. 判断对象是否为空
javascript·数据结构·算法·leetcode·职场和发展
goodluckyaa4 小时前
LCR 006. 两数之和 II - 输入有序数组
算法
孤狼warrior4 小时前
YOLO目标检测 一千字解析yolo最初的摸样 模型下载,数据集构建及模型训练代码
人工智能·python·深度学习·算法·yolo·目标检测·目标跟踪
Σίσυφος19004 小时前
PCL法向量估计 之 RANSAC 平面估计法向量
算法·机器学习·平面
xhbaitxl4 小时前
算法学习day39-动态规划
学习·算法·动态规划
I_LPL4 小时前
day23 代码随想录算法训练营 回溯专题2
算法·hot100·回溯算法·求职面试