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

LeetCode --- 156双周赛

题目列表

3541. 找到频率最高的元音和辅音
3542. 将所有元素变为 0 的最少操作次数
3543. K 条边路径的最大边权和
3544. 子树反转和

一、找到频率最高的元音和辅音

在这里插入图片描述
分别统计元音和辅音的出现次数最大值,然后相加即可,代码如下

// C++
class Solution {const string str = "aeiou";
public:int maxFreqSum(string s) {int cnt[26]{};int mx1 = 0, mx2 = 0;for(auto & e : s){cnt[e - 'a']++;if(str.find(e) == string::npos){mx1 = max(mx1, cnt[e - 'a']); // 更新辅音}else{mx2 = max(mx2, cnt[e - 'a']); // 更新辅音}}return mx1 + mx2;}
};
# Python
class Solution:def maxFreqSum(self, s: str) -> int:cnt = [0] * 26mx1 = 0mx2 = 0for e in s:x = ord(e) - ord('a')cnt[x] += 1if e in "aeiou":mx1 = max(mx1, cnt[x])else:mx2 = max(mx2, cnt[x])return mx1 + mx2

二、将所有元素变为 0 的最少操作次数

在这里插入图片描述
本题的难点在于一旦我们将区间内的最小值变为 0,那么剩余的不为 0 的数字就会被分成一段一段的区间,此时,我们需要在这些区间内再去进行操作,而这需要我们维护区间内的最小值,显然很困难,那有没有什么其他的思路?

  • 思路
    对于一个数字 x 来说,只有当它是区间内的最小值时,才可以通过操作被置为 0,而从贪心的角度来说,这个区间越大,则置为 0 的数越多,所进行的操作就会越少。所以我们只要计算对于同一个数字 x,它需要被分为多少个区间,才能让所有的 x 全部变为 0,而它分出的区间数就是它需要进行的最少操作次数。统计所有的数字对于答案的贡献即可

    • 这里暗含一个贪心的策略,优先将小的数字置为 0 会更优,因为小的数字置为 0,它依旧是小的数字,不会影响大的数字的分区个数,但是反过来,大的数字置为 0,就有可能将小的数字分成更多的区间,导致操作次数变多
    • 故这里我们计算出每个数字区间个数后直接相加,看似不论顺序,实质是从小的数字开始进行操作
    • 求解 x 为最小数字的区间,本质是求距离 x 最近的比它小的数字下标,可以用单调栈来求解
// C++
class Solution {
public:int minOperations(vector<int>& nums) {int n = nums.size();stack<int> st;vector<int> left(n, -1), right(n, n);// 计算区间for(int i = 0; i < n; i++){while(st.size() && nums[st.top()] > nums[i]){right[st.top()] = i;st.pop();}st.push(i);}st = stack<int>();for(int i = n - 1; i >= 0; i--){while(st.size() && nums[st.top()] > nums[i]){left[st.top()] = i;st.pop();}st.push(i);}unordered_map<int,set<pair<int,int>>> mp;for(int i = 0; i < n; i++){mp[nums[i]].emplace(left[i], right[i]);}int ans = 0;for(auto& [x, st] : mp){if(x){ // x = 0 不需要进行操作ans += st.size();}}return ans;}
};
  • 优化

    • 对于求区间个数的操作,我们可以在一次循环中得到,具体如下
// C++
class Solution {
public:int minOperations(vector<int>& nums) {int n = nums.size(), ans = 0;stack<int> st; // 单调递增 & 栈中无重复数字 & 不包含 0for(int i = 0; i < n; i++){while(st.size() && nums[st.top()] >= nums[i]){// 这里只统计一定需要进行一次操作的数字个数,即左右边界已经明确的数字// 和 nums[i] 相同的数字,由于右边界还不确定,此处不统计,等区间明确后在统计if(nums[st.top()] != nums[i]){ans++;}st.pop();}if(nums[i]) // 0 不需要入栈st.push(i);}// 栈中剩余的数字,此时右边界已经确定,也需要进行一次操作才能被置为 0return ans + st.size();}
};
#Python
class Solution:def minOperations(self, nums: List[int]) -> int:ans = 0bottom, top = 0, 0 # 可以直接将 nums 当作栈进行使用,空间复杂度为 O(1)for i in range(len(nums)):while bottom != top and nums[top-1] >= nums[i]:if nums[top-1] != nums[i]:ans += 1top -= 1if nums[i] > 0:nums[top] = nums[i]top += 1return ans + top - bottom

三、K 条边路径的最大边权和

在这里插入图片描述
本题先建图,然后直接用 dfs 进行遍历即可,注意,为了防止重复遍历某个状态,需要记忆化已经遍历过的状态,代码如下

// C++
class Solution {
public:int maxWeight(int n, vector<vector<int>>& edges, int k, int t) {vector<vector<pair<int,int>>> g(n);for(auto& e : edges){g[e[0]].emplace_back(e[1], e[2]);}int ans = -1;set<tuple<int,int,int>> st; // 记忆化遍历过的状态auto dfs = [&](this auto&& dfs, int x, int d, int s)->void{if(d == k){ans = max(ans, s);return;}if(st.count({x, d, s}))return;st.emplace(x, d, s);for(auto& [y, w] : g[x]){if(s + w < t){dfs(y, d + 1, w + s);}}};for(int i = 0; i < n; i++){dfs(i, 0, 0);}return ans;}
};
# Python
class Solution:def maxWeight(self, n: int, edges: List[List[int]], k: int, t: int) -> int:g = [[] for _ in range(n)]for x, y, w in edges:g[x].append((y, w))ans = -1@cachedef dfs(x:int, d:int, s:int):if d == k:nonlocal ansans = max(ans, s)returnfor y, w in g[x]:if w + s < t:dfs(y, d + 1, w + s)for i in range(n):dfs(i, 0, 0)return ans

四、子树反转和

在这里插入图片描述

本题的反转操作有距离限制,也就是说对当前结点进行反转操作之后,与它距离小于 k 的结点就不能进行反转操作了,所以我们在 dfs 遍结点的时候,需要增加两个参数 mul : 表示当前的结点取正还是取负cd : 多少距离后,就能再次进行反转操作,故我们有 dfs(x,fa,mul,cd)

  • x 结点不反转时, d f s ( x , f a , m u l , c d ) = s u m ( d f s ( y , x , m u l , ( c d ? c d − 1 , 0 ) ) ) + ( m u l ? n u m s [ x ] : − n u m s [ x ] ) dfs(x,fa,mul,cd)=sum(dfs(y,x,mul,(cd\ ?\ cd-1,0)))+(mul\ ?\ nums[x]\ : \ -nums[x]) dfs(x,fa,mul,cd)=sum(dfs(y,x,mul,(cd ? cd1,0)))+(mul ? nums[x] : nums[x]),其中 y 是结点 x 的所有子节点
  • x 结点反转且 cd == 0 时, d f s ( x , f a , m u l , c d ) = s u m ( d f s ( y , x , ! m u l , k − 1 ) ) + ( m u l ? − n u m s [ x ] : n u m s [ x ] ) dfs(x,fa,mul,cd)=sum(dfs(y,x,!mul,k-1))+(mul\ ?\ -nums[x]\ : \ nums[x]) dfs(x,fa,mul,cd)=sum(dfs(y,x,!mul,k1))+(mul ? nums[x] : nums[x]),其中 y 是结点 x 的所有子节点

代码如下

// C++
class Solution {
public:long long subtreeInversionSum(vector<vector<int>>& edges, vector<int>& nums, int k) {int n = nums.size();vector<vector<int>> g(n);for(auto & e : edges){g[e[0]].push_back(e[1]);g[e[1]].push_back(e[0]);}vector memo(n, vector(2, vector<long long>(k, -1)));auto dfs = [&](this auto&& dfs, int x, int fa, bool mul, int cd)->long long{ // f0, cd0, f1if(memo[x][mul][cd] != -1) return memo[x][mul][cd];long long res = mul ? nums[x] : -nums[x];for(int y : g[x]){if(y != fa){res += dfs(y, x, mul, (cd ? cd - 1 : 0));}}if(cd == 0){long long res2 = mul ? -nums[x] : nums[x];for(int y : g[x]){if(y != fa){res2 += dfs(y, x, !mul, k - 1);}}res = max(res, res2);}return memo[x][mul][cd] = res;};return dfs(0, -1, true, 0);}
};
# Python
class Solution:def subtreeInversionSum(self, edges: List[List[int]], nums: List[int], k: int) -> int:n = len(nums)g = [[] for _ in range(n)]for x,y in edges:g[x].append(y)g[y].append(x)memo = {}def dfs(x:int, fa:int, mul:bool, cd:int)->int:t = (x, mul, cd)if t in memo:return memo[t]res = nums[x] if mul else -nums[x]for y in g[x]:if y != fa:res += dfs(y, x, mul, cd - 1 if cd > 0 else 0)if cd == 0:res2 = -nums[x] if mul else nums[x]for y in g[x]:if y != fa:res2 += dfs(y, x, not mul, k - 1)res = max(res, res2)memo[t] = resreturn resreturn dfs(0, -1, True, 0)

相关文章:

  • ubuntu 24.04安装ros1 noetic
  • 2022河南CCPC(前四题)
  • js中不同循环的使用以及结束循环方法
  • Spring Boot 中 MyBatis 与 Spring Data JPA 的对比介绍
  • NHANES指标推荐:FMI
  • 介词有感2
  • 数据库故障排查指南:从紧急响应到根因分析【DeepSeek创作】
  • Ulyssess Ring Attention
  • Android同屏采集并推送RTMP和启动轻量级RTSP服务技术实践
  • 深入了解Javascript局部变量
  • JavaScript运算符
  • DAY 28 类的定义和方法
  • 布隆过滤器介绍及其在大数据场景的应用
  • linux-软件的安装与部署、web应用部署到阿里云
  • 【高斯拟合最终篇】Levenberg-Marquardt(LM)算法
  • Java Records:简洁的数据建模新方式
  • 类方法_静态方法_实例方法
  • 算法:分治法
  • Python训练营打卡Day28(2025.5.17)
  • 小白学习java第19天(下):spring
  • 小米汽车回应部分SU7前保险杠形变
  • 体坛联播|热刺追平单赛季输球纪录,世俱杯或创收20亿美元
  • 上海市税务局:收到对刘某某存在涉税问题的举报,正依法依规办理
  • 丹麦外交大臣拉斯穆森将访华
  • 在古老的意大利科莫歌剧院,廖昌永唱响16首中国艺术歌曲
  • 人民日报仲音:大力纠治违规吃喝顽瘴痼疾