pair<int, TreeNode*> dfs

lc865

pair<int, TreeNode*> dfs

计算每个节点左右子树高度,若左右子树高度相同则当前节点是最深节点的最近公共祖先++return {left_height + 1, node};++// 一样高,否则取高度更高子树的祖先

最终返回包含所有最深节点的最小子树的根节点

class Solution {

pair<int, TreeNode*> dfs(TreeNode* node) {

if (node == nullptr)

return {0, nullptr};

auto [left_height, left_lca] = dfs(node->left);

auto [right_height, right_lca] = dfs(node->right);

if (left_height > right_height) { // 左子树更高

return {left_height + 1, left_lca};

}

if (left_height < right_height) { // 右子树更高

return {right_height + 1, right_lca};

}

++return {left_height + 1, node};++ // 一样高

}

public:

TreeNode* subtreeWithAllDeepest(TreeNode* root) {

return dfs(root).second;

}

};

lc902

++数位dp 一种别人设计好了的状态转移套路++

  1. init:

将数字n转为字符串s(便于逐位处理)

  1. dfs:参数:

当前处理位i、是否受原数限制is_limit、是否已构成合法数字is_num,返回当前状态下的合法方案数

  1. 终止条件处理:

若遍历完所有位(i==m),返回is_num(1表示合法方案,0表示无效前导零情况);

  1. 状态枚举与递归:

先处理"跳过当前位"的无数字情况,再确定当前位可填数字上限,遍历给定数字集合中不超过上限的数字,递归计算下一位结果并累加;

  1. 记忆化:若当前状态不受原数限制且已构成合法数字,将结果存入dp供后续复用

dfs(第0位、受限状态、++未构成数字开始)++

class Solution {

public:

int atMostNGivenDigitSet(vector<string> &digits, int n) {

auto s = to_string(n);

int m = s.length(), dp[m];

memset(dp, -1, sizeof(dp));

function<int(int, bool, bool)> f = [&](int i, bool is_limit, ++bool is_num++ ) -> int {

++if (i == m) return is_num;++ // 如果填了数字,则为 1 种合法方案

if (!is_limit && ++is_num++ && dp[i] >= 0) return dp[i]; // 在不受到任何约束的情况下,返回记录的结果,避免重复运算

int res = 0;

++if (!is_num)++ // 前面不填数字,那么可以跳过当前数位,也不填数字

// is_limit 改为 false,因为没有填数字,位数都比 n 要短,自然不会受到 n 的约束

// is_num 仍然为 false,因为没有填任何数字

res = f(i + 1, false, ++false);++

++char up = is_limit ? s[i] : '9';++ // 根据是否受到约束,决定可以填的数字的上限

// 注意:对于一般的题目而言,如果这里 is_num 为 false,则必须从 1 开始枚举,由于本题 digits 没有 0,所以无需处理这种情况

for (auto &d : digits) {

// 枚举要填入的数字 d

if (d[0] > up) break; // d 超过上限,由于 digits 是有序的,后面的 d 都会超过上限,故退出循环

// is_limit:如果当前受到 n 的约束,且填的数字等于上限,那么后面仍然会受到 n 的约束

// is_num 为 true,因为填了数字

res += f(i + 1, is_limit && d[0] == up, true);

}

if (!is_limit && is_num) dp[i] = res; // 在不受到任何约束的情况下,记录结果

return res;

};

return f(0, true, ++false);++

}

};

lc1648

二分确定最高售价阈值

先对++高于阈值的球按等差数列求和计算收益,++再用阈值价格补齐剩余订单

最终得到最大利润

typedef long long ll;

class Solution {

private:

static constexpr int MOD = 1e9 + 7;

public:

int maxProfit(vector<int>& inventory, int orders) {

//每次都买剩余数量最大的一筐

//二分球卖出的价格阈值k

//需要注意不一定所有的球都按照阈值出售, 优先二分大于k的球

//如果卖出的数量不足orders, 则按照阈值k出售剩下的球

//用户只想买orders个球

int total = 0;

int lhs = 1, rhs = *max_element(inventory.begin(), inventory.end());

auto check = [&](int k) -> bool{

int sales = 0;

//优先卖出价格大于k的球

for (int x: inventory){

sales += max(x - k, 0);

if (sales > orders)

return true;

}

return false;

};

//lhs使得卖出的球数量小于等于orders

while (lhs <= rhs){

int mid = lhs + (rhs - lhs) / 2;

++if (check(mid))++

lhs = mid + 1;

else

rhs = mid - 1;

}

ll res = 0;

for (int x: inventory){

if (x > lhs){

//等差数列求和 (首项 + 末项)* 项数 / 2

++res += ((ll)(x - lhs) * (ll)(x + lhs + 1)) / 2;++

res %= MOD;

orders -= x - lhs;

}

}

//如果有剩余的order, 则一定按照阈值k的价格出售

res += (ll)lhs * orders;

res %= MOD;

return res;

}

};

lc1992

BFS遍历农田矩阵,找到每块连续农田的左上角起点后,扩展找到其右下角终点,收集所有农田的起点-终点坐标组返回

class Solution

{

public:

const int dirs[4][2] {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

vector<vector<int>> land;

int Row;

int Col;

pair<int, int> bfs(int sr, int sc)

{

int r2 = sr;

int c2 = sc;

queue<pair<int, int>> q;

q.push({sr, sc});

while (!q.empty())

{

auto [r, c] = q.front(); q.pop();

r2 = max(r2, r);

c2 = max(c2, c);

for (int di = 0; di < 4; di ++)

{

int dr = dirs[di][0], dc = dirs[di][1];

int nr = r + dr, nc = c + dc;

if (0 <= nr && nr < Row && 0 <= nc && nc < Col && land[nr][nc] == 1)

{

++land[nr][nc] = 0;
q.push({nr, nc});
++

}

}

}

return pair<int, int>{r2, c2};

}

vector<vector<int>> findFarmland(vector<vector<int>>& land)

{

this->land = land;

Row = (int)land.size();

Col = (int)land[0].size();

vector<vector<int>> res;

for (int r = 0; r < Row; r ++)

{

for (int c = 0; c < Col; c ++)

{

if (this->land[r][c] == 1)

{

this->land[r][c] = 0;

++auto [r2, c2] = bfs(r, c);
res.push_back(vector<int>{r, c, r2, c2});
++

}

}

}

return res;

}

};

相关推荐
初晴や17 小时前
【C++】图论:基础理论与实际应用深入解析
c++·算法·图论
李泽辉_17 小时前
深度学习算法学习(五):手动实现梯度计算、反向传播、优化器Adam
深度学习·学习·算法
李泽辉_18 小时前
深度学习算法学习(一):梯度下降法和最简单的深度学习核心原理代码
深度学习·学习·算法
꧁Q༒ོγ꧂18 小时前
算法详解---大纲
算法
m0_6038887118 小时前
Scaling Trends for Multi-Hop Contextual Reasoning in Mid-Scale Language Models
人工智能·算法·ai·语言模型·论文速览
Xの哲學18 小时前
Linux io_uring 深度剖析: 重新定义高性能I/O的架构革命
linux·服务器·网络·算法·边缘计算
comli_cn18 小时前
残差链接(Residual Connection)
人工智能·算法
Aaron158818 小时前
基于VU13P在人工智能高速接口传输上的应用浅析
人工智能·算法·fpga开发·硬件架构·信息与通信·信号处理·基带工程
予枫的编程笔记18 小时前
【论文解读】DLF:以语言为核心的多模态情感分析新范式 (AAAI 2025)
人工智能·python·算法·机器学习