【Leetcode第285场周赛】——周赛总结

1、6027. 统计数组中峰和谷的数量 - 力扣(LeetCode) (leetcode-cn.com)

给你一个下标从 0 开始的整数数组 nums 。如果两侧距 i 最近的不相等邻居的值均小于 nums[i] ,则下标 i 是 nums 中某个峰的一部分。类似地,如果两侧距 i 最近的不相等邻居的值均大于 nums[i] ,则下标 i 是 nums 中某个谷的一部分。对于相邻下标 i 和 j ,如果 nums[i] == nums[j] , 则认为这两下标属于 同一个 峰或谷。

注意,要使某个下标所做峰或谷的一部分,那么它左右两侧必须 都 存在不相等邻居。

返回 nums 中峰和谷的数量。

 

模拟题,直接按题意来就行了,注意题中要找的是不相等的邻居。需要排除掉相等邻居的情况。

class Solution {
public:
int countHillValley(vector<int>& nums) {
int n=nums.size();
int sumP=0,sumV=0;
for(int i=1;i<n-1;i++){
int j=i-1,k=i+1;
if(nums[i]==nums[i-1])
continue;
if(nums[k]==nums[i]){
while(k<n-1){
if(nums[k]!=nums[i])
break;
k++;
}
}
if(nums[j]==nums[i]){
while(j>0){
if(nums[j]!=nums[i])
break;
j--;
}
}
if(nums[i]>nums[k]&&nums[i]>nums[j])
sumP++;
if(nums[i]<nums[k]&&nums[i]<nums[j])
sumV++;
}
return sumV+sumP;
}
};

2、6028. 统计道路上的碰撞次数 - 力扣(LeetCode) (leetcode-cn.com)

在一条无限长的公路上有 n 辆汽车正在行驶。汽车按从左到右的顺序按从 0 到 n - 1 编号,每辆车都在一个 独特的 位置。

给你一个下标从 0 开始的字符串 directions ,长度为 n 。directions[i] 可以是 'L'、'R' 或 'S' 分别表示第 i 辆车是向 左 、向 右 或者 停留 在当前位置。每辆车移动时 速度相同 。

碰撞次数可以按下述方式计算:

当两辆移动方向 相反 的车相撞时,碰撞次数加 2 。
当一辆移动的车和一辆静止的车相撞时,碰撞次数加 1 。
碰撞发生后,涉及的车辆将无法继续移动并停留在碰撞位置。除此之外,汽车不能改变它们的状态或移动方向。

返回在这条道路上发生的 碰撞总次数 。

 

这个题在周赛时没想明白,就一直卡在这里。。。其实就是个脑筋急转弯:在最左边的L和最右边的R永远不会发生碰撞,所以在排除最左侧的所有L和最右侧的所有R后,中间所有的车都会发生碰撞。

根据题意,“RL”碰撞次数+2————>有两辆车被撞停

                   ”RS“ or ”SL“碰撞次数+1——>有一辆车被撞停

所以我们直接统计中间的所有运动车辆即可。

 

class Solution {
public:
int countCollisions(string directions) {
int n=directions.length();
int l=0,r=n-1;
while(l<=r&&directions[l]=='L') l++;
while(l<=r&&directions[r]=='R') r--;
int res=0;
for(int i=l;i<=r;++i){
if(directions[i]=='R'||directions[i]=='L'){
res++;
}
}
return res;
}
};

3、6029. 射箭比赛中的最大得分 - 力扣(LeetCode) (leetcode-cn.com)

所以说人不能在一棵树上吊死,这题其实方法之前我都见过,按道理应当可以拿下,结果却因为第二题没转过弯来导致这题没好好思考。。。周赛时一直在debug第二题,觉得自己方法没错。。。唉,得吸取教训。

方法一:0/1背包问题+路径还原

这道题可以看成是0/1背包问题——一共有12件物品,每一件物品i的权重为aliceArrows[i]+1,有一个大小为numsArrows的背包,求背包所能容纳的物品的最大权重和。

这道题还多了一步:要求我们回溯出路径,找到拿的哪几件物品,也算是一个小小的难点。

class Solution {
public:
vector<int> maximumBobPoints(int numArrows, vector<int>& aliceArrows) {
vector<vector<int>> dp(12,vector<int>(numArrows+1,0));
for(int i=1;i<12;i++){ //正常的0/1背包求解,找到最大容量
for(int j=1;j<=numArrows;j++){
if(j>aliceArrows[i]){
dp[i][j]=max(dp[i-1][j],dp[i-1][j-aliceArrows[i]-1]+i);
}
else{
dp[i][j]=dp[i-1][j];
}
}
}
vector<int> ans(12,0);
for(int i=11;i>0;--i){ //路径还原
if(dp[i][numArrows]>dp[i-1][numArrows]){ //证明有过射箭行为
ans[i]=aliceArrows[i]+1;
numArrows-=ans[i];
}
}
ans[0]=numArrows; //统计完前面的所有有分的情况后,如果箭有剩余则证明全射在0区域,不得分
return ans;
}
};

方法二:二进制枚举

题目中射箭区域长度为12,可以使用一个二进制数来枚举出所有的情况,并不断更新最大分数以及对应的射箭情况。

 

class Solution {
public:
vector<int> maximumBobPoints(int numArrows, vector<int>& aliceArrows) {
int n=aliceArrows.size();
int curScore;
int maxScore=0;
int usedArrows;
vector<int> ans(12);
for(int i=0;i<(1<<n);i++){ //枚举出所有的2048种情况
curScore=0;
usedArrows=0;
vector<int> bob(12); //枚举所有情况
for(int j=0;j<n;j++){
if(((i>>j)&1)==1){ //若bob射在了aliceArrows[j]处
usedArrows+=aliceArrows[j]+1;
curScore+=j;
bob[j]=aliceArrows[j]+1;
}
}
if(usedArrows<=numArrows&&curScore>maxScore){ //箭有剩余且当前分数大于已记录的最大分数
ans=bob;
maxScore=curScore;
ans[0]+=numArrows-usedArrows;
}
}
return ans;
}
};

4、6030. 由单个字符重复的最长子字符串 - 力扣(LeetCode) (leetcode-cn.com)

给你一个下标从 0 开始的字符串 s 。另给你一个下标从 0 开始、长度为 k 的字符串 queryCharacters ,一个下标从 0 开始、长度也是 k 的整数 下标 数组 queryIndices ,这两个都用来描述 k 个查询。

第 i 个查询会将 s 中位于下标 queryIndices[i] 的字符更新为 queryCharacters[i] 。

返回一个长度为 k 的数组 lengths ,其中 lengths[i] 是在执行第 i 个查询 之后 s 中仅由 单个字符重复 组成的 最长子字符串 的 长度 。

 

本题由于使用到了线段树的有关思想,超出了笔者的知识范畴,所以不在此班门弄斧,在此附上大佬灵茶山艾府的题解,有兴趣的读者可以自行前去学习和字符集大小无关的线段树做法 - 由单个字符重复的最长子字符串 - 力扣(LeetCode) (leetcode-cn.com)


__EOF__

本文作者天涯海角寻天涯
本文链接https://www.cnblogs.com/yjx-7355608/p/16031394.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   天涯海角寻天涯  阅读(107)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
点击右上角即可分享
微信分享提示