当前位置: 首页 > news >正文

[leetcode ] 5.29week | dp | 组合数学 | 图 | 打家劫舍

字典序 直接调用的 API

WA 了一次,注意==1 的鲁棒性


代码:

class Solution {
public:vector<int> maxTargetNodes(vector<vector<int>>& edges1, vector<vector<int>>& edges2, int k) {int n1 = edges1.size(), n2 = edges2.size();int n = 0, m = 0;for(auto c:edges1){n = max(max(c[0],c[1]),n);}for(auto c:edges2){m = max(max(c[0],c[1]),m);}vector<vector<int>>xy1(n+1), xy2(m+1);for(auto c:edges1){int a = c[0], b = c[1];xy1[a].push_back(b);xy1[b].push_back(a);}for(auto c:edges2){int a = c[0], b = c[1];xy2[a].push_back(b);xy2[b].push_back(a);}vector<int>sum1(n+1,0), sum2(m+1,0);int mx1 = 0, mx2 = 0;for(int i=0;i<=n;i++){queue<int>qu;int k_ = k;int sum = 1;if(k_==1)mx1 = max(mx1,sum);qu.push(i);vector<bool>st(n+1,true);st[i]=false;while(k_>0){k_--;int sz = qu.size();while(sz>0){sz--;int tp = qu.front();qu.pop();for(auto c:xy1[tp]){if(st[c]==true){ qu.push(c);st[c]=false;}}}sum += qu.size();if(k_==1)mx1 = max(mx1,sum);}sum1[i] = sum;}for(int i=0;i<=m;i++){queue<int>qu;int k_ = k;int sum = 1;if(k_==1)mx2 = max(mx2,sum);qu.push(i);vector<bool>st(m+1,true);st[i]=false;while(k_>0){k_--;int sz = qu.size();while(sz>0){sz--;int tp = qu.front();qu.pop();for(auto c:xy2[tp]){if(st[c]==true){ qu.push(c);st[c]=false;}}}sum += qu.size();if(k_==1)mx2 = max(mx2,sum);}sum2[i] = sum;}vector<int>ans(n+1,0);for(int i=0;i<=n;i++){ans[i] = sum1[i] + mx2;}return ans;}
};


🌟题目大意(简化版)

我们有两棵树(Tree 1 和 Tree 2),每棵树由边列表给出。我们要做的是:

  • 把 Tree 1 的每个节点 连接到 Tree 2 的某个节点
  • 然后从这个连接出发,在一定限制下(比如最多走几步)能到达多少个目标节点;
  • 我们希望找出:对于 Tree 1 中的每一个节点,它最多能连接到多少个目标节点。

💡核心思路(白话讲解)

第一步:树是“国际象棋棋盘”

我们可以把一棵树上的所有节点想象成像国际象棋棋盘一样:

  • 相邻节点颜色不同(黑→白→黑……)
  • 这样就形成了两个组:
    • 组0:距离根节点(比如节点0)为偶数步的节点
    • 组1:距离根节点为奇数步的节点

这就叫做按奇偶分层,用 DFS 或 BFS 就能做到。


第二步:找第二棵树的最大潜力

对 Tree 2:

  • 我们把它也分成两个组(组0 和 组1);
  • 看哪一组节点更多,我们就选那一组作为通用连接对象;
  • 记录最大值 max2 = max(组0数量, 组1数量)

第三步:给第一棵树的每个节点算答案

对 Tree 1:

  • 每个节点属于组0或组1;
  • 它的目标节点只能在它自己这一组里;
  • 再加上 Tree 2 的最大组数量(max2);
  • 所以答案就是:自己的组大小 + max2

🧠举个例子(帮助理解)

假设 Tree 1 分成了:

  • 组0 有 5 个节点
  • 组1 有 3 个节点

Tree 2 分成了:

  • 组0 有 4 个节点
  • 组1 有 6 个节点 → 最大是 6

那么:

  • Tree 1 中属于组0的节点的答案是:5 + 6 = 11
  • 属于组1的节点的答案是:3 + 6 = 9

总结

  • 树是“没有环”的结构,可以 DFS/BFS 遍历;
  • 树一定是“二分图”,可以用黑白染色;
  • 染色后就可以按颜色(奇偶)分组统计;
  • 答案构造很简单:自己组的大小 + 别人最大的组大小。
class Solution {
public:vector<int> maxTargetNodes(vector<vector<int>>& edges1, vector<vector<int>>& edges2) {auto count = [](vector<vector<int>>& edges) {vector<vector<int>> g(edges.size() + 1);//把边列表转换成邻接表(也就是一个图的结构,方便遍历)for (auto& e : edges) {int x = e[0], y = e[1];g[x].push_back(y);g[y].push_back(x);}//用 DFS 遍历整棵树,统计每个节点离根节点的距离是奇数还是偶数,分别计数array<int, 2> cnt{};auto dfs = [&](this auto&& dfs, int x, int fa, int d) -> void {cnt[d]++;for (int y : g[x]) {if (y != fa) {dfs(y, x, d ^ 1);}}};dfs(0, -1, 0);return pair(g, cnt);};//统计 Tree 2 的两个组的大小,取最大值作为通用连接对象auto [_, cnt2] = count(edges2);int max2 = max(cnt2[0], cnt2[1]);//统计 Tree 1 的两个组的大小,先让每个节点带上 Tree 2 的最大值auto [g, cnt1] = count(edges1);vector<int> ans(g.size(), max2);//再次 DFS 遍历 Tree 1,根据当前节点属于哪个组,加上它自己这组的数量,最终得到答案auto dfs = [&](this auto&& dfs, int x, int fa, int d) -> void {ans[x] += cnt1[d];for (int y : g[x]) {if (y != fa) {dfs(y, x, d ^ 1);}}};dfs(0, -1, 0);return ans;}
};

枚举第一个小朋友拿的糖果数量,再结合剩下糖果在另外两个小朋友之间的合法分配方式,最终统计所有可能的分法总数

if (left > 2 * limit)  continue;if (limit >= left)  res += left + 1;else  res += (limit - (left - limit)) + 1;

简单组合数学知识:
可能情况总数 = (上限 - 下限) + 1

class Solution {
public:long long distributeCandies(int n, int limit) {long long res = 0;for (int i = 0; i <= min(limit, n); ++i) {// 第一个人拿了 i 个糖果int left = n - i;// 剩下的两个孩子每人最多 limit,总共最多 2 * limitif (left > 2 * limit) {continue;}if (limit >= left) {res += left + 1;} else {// 可能情况总数 = (上限 - 下限) + 1res += (limit - (left - limit)) + 1;}}return res;}
};

dp依照三个位置
“每个人要比左右评分更高的孩子拿到更多的糖果” → 从左到右、从右到左各扫一遍填表

  • 感觉就是爬坡。先全部设置为最小值1
  • 正向遍历,如果相邻的比自己大就加1
  • 反向遍历,如果相邻的比自己大也加1,取最大值

代码

class Solution {
public:int candy(vector<int>& ratings) {int n = ratings.size();vector<int> dp(n, 1); // 初始每人至少一颗糖// 从左往右看,确保评分更高的孩子糖果也更多for(int i = 1; i < n; i++){if(ratings[i] > ratings[i - 1])dp[i] = dp[i - 1] + 1;}// 从右往左看for(int i = n - 2; i >= 0; i--){if(ratings[i] > ratings[i + 1])dp[i] = max(dp[i], dp[i + 1] + 1);}int total = 0;for(int d : dp)total += d;return total;}
};

打家劫舍

二维 dp 来实现选择,选 A or 选 B

代码:

class Solution {
public:long long maxEnergyBoost(vector<int>& A, vector<int>& B) {int n = A.size();long long f[n][2];f[0][0] = A[0]; f[0][1] = B[0];for (int i = 1; i < n; i++) {f[i][0] = max(f[i - 1][0] + A[i], f[i - 1][1]); //刚换过来的 当前步是不能喝的f[i][1] = max(f[i - 1][1] + B[i], f[i - 1][0]);}return max(f[n - 1][0], f[n - 1][1]);}
};

相关文章:

  • grep命令常见用法
  • Dataguard switchover遇到ORA-19809和ORA-19804报错的问题处理
  • C# 从 ConcurrentDictionary 中取出并移除第一个元素
  • GRU 参数梯度推导与梯度消失分析
  • LeetCode-934. 最短的桥
  • PPTAGENT:让PPT生成更智能
  • 在 Spring Boot 中使用 WebFilter:实现请求拦截、日志记录、跨域处理等通用逻辑!
  • C++多态与继承实战解析
  • GDB的调试
  • 11. 试学内容-如何理解隔离性2(原理)
  • Android 颜色百分比对照
  • C#编程过程中变量用中文有啥影响?
  • 23树与左倾红黑树
  • 飞算JavaAI 炫技赛重磅回归!用智能编码攻克老项目重构难题
  • SpringCloudAlibaba微服务架构
  • 《T/CI 404-2024 医疗大数据智能采集及管理技术规范》全面解读与实施分析
  • 0. MySQL在Centos 7环境安装
  • 区块链技术发展现状与应用前景分析
  • c++返回对象,返回引用,返回指针有什么区别?
  • spel 多层list嵌套表达式踩坑记
  • 江苏住房和城乡建设厅网站首页/百度seo网站在线诊断
  • 做logo专用的网站是哪个/某网站搜索引擎优化
  • 广州网站改版设计公司/销售新手怎么找客源
  • 个人网页设计模板图片手机版/廊坊百度提升优化
  • wordpress单位内网做网站/优化系统
  • 网站客服用百度商桥好吗/如何自己弄个免费网站