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;
}
思路:
-
遍历数组,维护前缀和sum(前i+1个数的总和);
-
对于每个位置i,计算前i+1个数的平均值的上取整
-
所有位置的这个"平均值上取整"的最大值,就是答案。
举个例子(输入[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;
}
};
-
用哈希表记录每个数字出现的所有位置;
-
对每个数字的位置数组,用++滑动窗口维护"删除不超过k个元素"的区间:++
-
++窗口内需要删除的元素数 = arr[right] - arr[left] - (right - left) (总长度 - 有效元素数);++
-
若删除数超过k,则左指针右移;
-
窗口长度( right-left+1 )即为当前数字的最大等值子数组长度。
这样就能高效求出删除最多k个元素后的最长等值子数组长度。