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

2023-03-10,

1、5268. 找出两数组的不同 - 力扣(LeetCode) (leetcode-cn.com)

给你两个下标从 0 开始的整数数组 nums1 和 nums2 ,请你返回一个长度为 2 的列表 answer ,其中:

answer[0] 是 nums1 中所有 不 存在于 nums2 中的 不同 整数组成的列表。
answer[1] 是 nums2 中所有 不 存在于 nums1 中的 不同 整数组成的列表。
注意:列表中的整数可以按 任意 顺序返回。

分析:简单模拟题,这里使用到了find()方法来寻找元素是否存在,也可以使用set来进行查找。

注意要去重

class Solution {
public:
vector<vector<int>> findDifference(vector<int>& nums1, vector<int>& nums2) {
sort(nums1.begin(),nums1.end());
sort(nums2.begin(),nums2.end());
int n1=nums1.size();
int n2=nums2.size();
vector<int> ans1;
vector<int> ans2;
int i=0,j=0;
for(i=0;i<n1;i++){
if(i-1>=0&&nums1[i]==nums1[i-1]) //去重
continue;
auto it=find(nums2.begin(),nums2.end(),nums1[i]);
if(it==nums2.end()){
ans1.push_back(nums1[i]);
}
}
for(j=0;j<n2;j++){
if(j-1>=0&&nums2[j]==nums2[j-1]) //去重
continue;
auto it=find(nums1.begin(),nums1.end(),nums2[j]);
if(it==nums1.end()){
ans2.push_back(nums2[j]);
}
}
return {ans1,ans2};
}
};

2、5236. 美化数组的最少删除数 - 力扣(LeetCode) (leetcode-cn.com)

给你一个下标从 0 开始的整数数组 nums ,如果满足下述条件,则认为数组 nums 是一个 美丽数组 :

nums.length 为偶数
对所有满足 i % 2 == 0 的下标 i ,nums[i] != nums[i + 1] 均成立
注意,空数组同样认为是美丽数组

你可以从 nums 中删除任意数量的元素。当你删除一个元素时,被删除元素右侧的所有元素将会向左移动一个单位以填补空缺,而左侧的元素将会保持 不变 。

返回使 nums 变为美丽数组所需删除的 最少 元素数目。

分析:模拟,按照题意判断下标i为偶数的时候是否满足nums[i]==nums[i+1],如果满足那么就将nums[i]删除,答案+1。

因为我们只需要统计个数,所以没有必要去真的将元素从数组中删去,且根据题意删除元素后右侧所有元素都会自动向左补充一位。因此在判断下标奇偶性时需要将已经删除的元素个数当作偏移量减去。

class Solution {
public:
int minDeletion(vector<int>& nums) {
int n=nums.size();
if(n==1)
return 1;
int ans=0;
for(int i=0;i<n-1;i++){
if((i-ans)%2==0){
if(nums[i]==nums[i+1]){
ans++;
}
}
}
if((n-1-ans)%2==0){ //最后一个元素由于右端没有元素,默认满足nums[i]!=nums[i+1],所以当其下标为偶数时也需要删除
ans++;
}
return ans;
}
};

3、5253. 找到指定长度的回文数 - 力扣(LeetCode) (leetcode-cn.com)

给你一个整数数组 queries 和一个 正 整数 intLength ,请你返回一个数组 answer ,其中 answer[i] 是长度为 intLength 的 正回文数 中第 queries[i] 小的数字,如果不存在这样的回文数,则为 -1 。

回文数 指的是从前往后和从后往前读一模一样的数字。回文数不能有前导 0 。

分析:题意很简单,就是要我们求给定数位下第queries[i]小的回文数,所以这题就转成了求回文数,不会求回文数就很痛苦了。。。

由于回文数具有对称性,所以我们只需要考虑前一半,然后将其反转拼接到后一半就行了。

回文数的前一半为

因此,我们将该数反转后拼接到后面即是答案。

当intLength为奇数时,需要将最后一位去掉再拼接。

举一个栗子:intLength=5,half=103,那么求解回文数的过程为:

res=103,half=10;

res=103*10+10%10=1030,half=10/10=1

res=1030*10+1%10=10301,half=1/10=0

end

class Solution {
public:
vector<long long> kthPalindrome(vector<int>& queries, int intLength) {
int n=queries.size();
vector<long long> ans;
for(auto& q:queries){
int n=queries.size();
long long half;
long long lh=1;
long long res;
for(int i=0;i<(intLength-1)/2;i++){ //求回文数前一半的基数
lh*=10;
}
half=lh+q-1; //第q小的回文数的前半部分
if(half>=10*lh){ //如果前半部分大于10*lh,说明第q小的回文数不存在,也就是说第q小的回文数已经超出了intLength长度的回文数的范围
ans.emplace_back(-1);
continue;
}
res=half;
if(intLength%2!=0){ //长度为奇数,去除掉最后一位
half/=10;
}
while(half!=0){ //拼接回文数
res=res*10+half%10;
half/=10;
}
ans.emplace_back(res);
}
return ans;
}
};

4、5269. 从栈中取出 K 个硬币的最大面值和 - 力扣(LeetCode) (leetcode-cn.com)

一张桌子上总共有 n 个硬币 栈 。每个栈有 正整数 个带面值的硬币。

每一次操作中,你可以从任意一个栈的 顶部 取出 1 个硬币,从栈中移除它,并放入你的钱包里。

给你一个列表 piles ,其中 piles[i] 是一个整数数组,分别表示第 i 个栈里 从顶到底 的硬币面值。同时给你一个正整数 k ,请你返回在 恰好 进行 k 次操作的前提下,你钱包里硬币面值之和 最大为多少 。

分析:这题我第一眼就觉得是用dp来做,而且跟背包问题很像,但是比赛时一直在debug第三题导致这题没做,还是需要多多练习啊。

这题是一个典型的分组背包问题:一共有N组物品,每一组内有若干物品,每个物品都有自己的价值和体积,现在有一个容量为W的背包,你可以从每组物品中至多挑选一个,求背包内能装下的最大物品价值。其解决思想与0/1背包问题相似:对于第i组有两种决策:拿或者不拿,状态转移方程为

dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i][k]]+v[i][k])

同理我们可以进行空间压缩,原理与0/1背包问题一样。最简单的背包问题——0/1背包问题 - 天涯海角寻天涯 - 博客园 (cnblogs.com)

在这道题里,由于题目设定是栈,因此我们只能够从中取出数组元素的前缀和。记前缀和数组为sum,那么sum[i]表示体积为i,价值为sum[i]的物品。

因此这道题就变成了:有piles.size()组物品,每一组中有若干物品,我们有一个容量为k的背包,现在我们需要从这几组物品中拿取物品装入背包,使得我们背包内的物品总价值最大。

class Solution {
public:
int maxValueOfCoins(vector<vector<int>>& piles, int k) {
vector<int> dp(k+1,0);
int W=0; //背包容量
for(auto& p:piles){
int n=p.size();
for(int i=1;i<n;i++){ //求栈中元素的前缀和
p[i]+=p[i-1];
}
W=min(W+n,k); //背包容量动态变化,如果取到W+n,说明当前栈中的所有硬币都可以拿取;
for(int j=W;j>=0;--j){
for(int i=0;i<min(n,j);i++){ //i最大不能超过栈的容量大小
dp[j]=max(dp[j],dp[j-i-1]+p[i]);
}
}
}
return dp[k];
}
};

【Leetcode第286场周赛】——周赛总结的相关教程结束。

《【Leetcode第286场周赛】——周赛总结.doc》

下载本文的Word格式文档,以方便收藏与打印。