预hash|vector<int> dfs

lc3429

for(int i=1;i<mem.size();i++) //check

if(mem[i]!=mem[0]) f=false;

++return cnt; //返回子树个数和++

class Solution {

/*

如果一个节点的所有子节点为根的 子树 包含的节点数相同,则认为该节点是一个 好节点。

*/

public:

int countGoodNodes(vector<vector<int>>& edges)

{

int n=edges.size()+1;

vector<vector<int>> g(n);

for(auto& e:edges)

{

g[e[0]].push_back(e[1]);

g[e[1]].push_back(e[0]);

}

int ret=0;

auto dfs=[&](this auto&& dfs,int p,int fa)->int

{

int cnt=1;

vector<int> mem;

bool f=true;

for(auto& e:g[p])

{

if(e!=fa)

{

int sub=dfs(e,p);

mem.push_back(sub);

cnt+=sub;

}

}

for(int i=1;i<mem.size();i++)

++if(mem[i]!=mem[0]) f=false;++

if(f) ret++;

++return cnt; //返回子树个数和++

};

dfs(0,-1);

return ret;

}

};

lc1530

DFS遍历树,++vector<int> dfs ++返回子++树中所有叶子到自己的距离++,统计左右子树叶子距离和≤目标值的对数,累加得到结果

trick

/++/ 统计左右子树叶子的合法对++

++for(int x:l) for(int y:r) if(x+y <= distance) ret++;++

class Solution

{

public:

int countPairs(TreeNode* root, int distance)

{

int ret=0;

auto dfs=[&](this auto&& dfs,TreeNode* node)->vector<int>

{

if(!node) return {};

if(!node->left && !node->right) return {1}; // 叶子节点,深度1

auto l=dfs(node->left), r=dfs(node->right);

/++/ 统计左右子树叶子的合法对++

++for(int x:l) for(int y:r) if(x+y <= distance) ret++;++

// 深度+1后返回

vector<int> res;

for(int x:l) res.push_back(x+1);

++for(int x:r) res.push_back(x+1);++

return res;

};

dfs(root);

return ret;

}

};

lc2439

将大的数'匀'给前面小的数,求最终数组的最大值的最小值

取决于前缀和的平均值上取整"的最大值------因为前面的数无法"转移"到后面,只能++让后面的大数向前匀++(比如第i位的数只能影响前i位)

int minimizeArrayValue(vector<int>& nums)

{

int n=nums.size();

vector<long long> p(n+1);

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

p[i]=p[i-1]+nums[i-1];

int ret=0;

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

{

++ret=max(ret,(int)((p[i]+i-1)/i));++

}

return ret;

}

思路:

  1. 遍历数组,维护前缀和sum(前i+1个数的总和);

  2. 对于每个位置i,计算前i+1个数的平均值的上取整

  3. 所有位置的这个"平均值上取整"的最大值,就是答案。

举个例子(输入[3,7,1,6]):

  • 前1位:sum=3 → 3/1=3

  • 前2位:sum=10 → 10/2=5

  • 前3位:sum=11 → 11/3≈3.67 → 上取整4

  • 前4位:sum=17 → 17/4≈4.25 → 上取整5

这些值的最大值是5,就是答案

lc2261

class Solution {

/*

输入:cards = [3,4,2,3,4,7]

输出:4

*/

public:

int minimumCardPickup(vector<int>& cards) {

unordered_map<int,vector<int>> hash;

int ret=INT_MAX;

for(int i=0;i<(int)cards.size();i++)

{

hash[cards[i]].push_back(i);

}

for(auto& [_,b]:hash)

{

int n=b.size();

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

{

ret=min(ret,b[i]-b[i-1]+1);

}

}

return ret==INT_MAX?-1:ret;

}

};

lc2813

hash预处理

窗口内需要删除的元素数 = arr[right] - arr[left] - (right - left) (总长度 - 有效元素数)

"删除最多k个元素后,得到最长的等值子数组"

统计每个数字的位置,用滑动窗口计算最大长度

class Solution {

public:

int longestEqualSubarray(vector<int>& nums, int k)

{

int n = nums.size();

int ret = 0;

// 统计每个数字对应的所有位置

unordered_map<int, vector<int>> pos;

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

pos[nums[i]].push_back(i);

}

// 对每个数字的位置数组,用滑动窗口计算最大长度

for (auto& [_, arr] : pos) {

int left = 0;

for (int right = 0; right < arr.size(); ++right) {//try right结尾的 max ret

// 窗口内需要删除的元素数 = 当前位置 - 窗口左位置 - (right - left)

while (arr[right] - arr[left] - (right - left) > k)

left++;

++ret = max(ret, right - left + 1);++

}

}

return ret;

}

};

  1. 用哈希表记录每个数字出现的所有位置;

  2. 对每个数字的位置数组,用++滑动窗口维护"删除不超过k个元素"的区间:++

  • ++窗口内需要删除的元素数 = arr[right] - arr[left] - (right - left) (总长度 - 有效元素数);++

  • 若删除数超过k,则左指针右移;

  • 窗口长度( right-left+1 )即为当前数字的最大等值子数组长度。

这样就能高效求出删除最多k个元素后的最长等值子数组长度。

相关推荐
mmz12071 小时前
双指针问题5(c++)
c++·算法
星空露珠1 小时前
lua获取随机颜色rgb转换hex
数据结构·数据库·算法·游戏·lua
Zsy_0510031 小时前
【数据结构】堆简单介绍、C语言实现堆和堆排序
c语言·数据结构·算法
Rock_yzh1 小时前
LeetCode算法刷题——56. 合并区间
数据结构·c++·学习·算法·leetcode·职场和发展·动态规划
sheeta19981 小时前
LeetCode 每日一题笔记 日期:2025.12.02 题目:3623. 统计梯形的数目 I
笔记·算法·leetcode
宇来风满楼1 小时前
U-KAN复现
人工智能·深度学习·神经网络·算法·机器学习
W_chuanqi1 小时前
单目标实数参数优化:算法jSO
算法
老鱼说AI1 小时前
算法初级教学第三步:链表
数据结构·算法·链表