【Leetcode第286場周賽】——周賽總結
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];
}
};