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

[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]);}
};
http://www.xdnf.cn/news/11962.html

相关文章:

  • 68 VG的基本信息查询
  • SQL 中 JOIN 的执行顺序优化指南
  • RAMSUN分享全新超值型MM32F0050系列MCU
  • 理解继承与组合的本质:Qt 项目中的设计选择指南
  • 如何量化创新项目的成功标准
  • js鼠标事件大全
  • 滚珠导轨在光学设备中如何实现微米级运动?
  • 简单网络拓扑实验
  • 第一篇:Liunx环境下搭建PaddlePaddle 3.0基础环境(Liunx Centos8.5安装Python3.10+pip3.10)
  • 30 C 语言递归算法详解:基准条件、递归逻辑、循环对比、经典案例(斐波那契、猴子吃桃、汉诺塔、二分查找等)
  • Maskrcnn网络结构学习
  • Ubuntu更新国内源
  • Python 训练营打卡 Day 43
  • Vue前端篇——项目目录结构介绍
  • NER实践总结,记录一下自己实践遇到的各种问题。
  • 【linux】全志Tina预编译一个so库文件到根文件系统/usr/lib/下
  • 拉深工艺模块——回转体拉深件毛坯尺寸的确定(二)
  • Vue2 和 Vue3 常见 CSS 样式归纳总结
  • PyTorch——优化器(9)
  • 近几年字节飞书测开部分面试题整理
  • 【计网】SW、GBN、SR、TCP
  • 深度学习之模型压缩三驾马车:模型剪枝、模型量化、知识蒸馏
  • Linux——TCP和UDP
  • 6月14日开班,ESG 合规分析师招生通知
  • FreeRTOS,MicroPython,区别与联系
  • 新制作文件系统占满:Error writing to file - write (28: No space left on device)
  • 雷卯针对易百纳 海思Hi3519AV100开发板防雷防静电方案
  • 虚拟机无法开启-关掉虚拟化
  • ROS中的里程计与IMU的消息类型解读
  • 深入解析异步爬虫中的协程原理:从概念到工程实践