LeetCode 第 186 场周赛(1060/3107,前34.1%)
文章目錄
- 1. 比賽結果
- 2. 題目
- 1. LeetCode 5392. 分割字符串的最大得分 easy
- 2. LeetCode 5393. 可獲得的最大點數 medium
- 3. LeetCode 5394. 對角線遍歷 II medium
- 4. LeetCode 5180. 帶限制的子序列和 hard
1. 比賽結果
做出來了 1、2 題,第3題模擬法,超時,第4題不會,繼續加油!
全國排名:1060 / 3107,34.1%;全球排名:4145 / 11687,35.5%
2. 題目
1. LeetCode 5392. 分割字符串的最大得分 easy
題目鏈接
給你一個由若干 0 和 1 組成的字符串 s ,請你計算并返回將該字符串分割成兩個 非空 子字符串(即 左 子字符串和 右 子字符串)所能獲得的最大得分。
「分割字符串的得分」為 左 子字符串中 0 的數量加上 右 子字符串中 1 的數量。
示例 1: 輸入:s = "011101" 輸出:5 解釋: 將字符串 s 劃分為兩個非空子字符串的可行方案有: 左子字符串 = "0" 且 右子字符串 = "11101",得分 = 1 + 4 = 5 左子字符串 = "01" 且 右子字符串 = "1101",得分 = 1 + 3 = 4 左子字符串 = "011" 且 右子字符串 = "101",得分 = 1 + 2 = 3 左子字符串 = "0111" 且 右子字符串 = "01",得分 = 1 + 1 = 2 左子字符串 = "01110" 且 右子字符串 = "1",得分 = 2 + 1 = 3示例 2: 輸入:s = "00111" 輸出:5 解釋:當 左子字符串 = "00" 且 右子字符串 = "111" 時, 我們得到最大得分 = 2 + 3 = 5示例 3: 輸入:s = "1111" 輸出:3提示: 2 <= s.length <= 500 字符串 s 僅由字符 '0' 和 '1' 組成。解答:
- 左右兩邊,前綴0,后綴1,一次遍歷即可
比賽的時候寫的有點繁瑣
4 ms 6.9 MB
賽后解
class Solution { public:int maxScore(string s) {int i, one = 0, maxs = 0, zero = 0;for(i = 0; i < s.size(); ++i){if(s[i]=='1')one++;}for(i = 0; i < s.size()-1; ++i){if(s[i]=='0')zero++;elseone--;maxs = max(maxs,zero+one);}return maxs;} };0 ms 6.4 MB
2. LeetCode 5393. 可獲得的最大點數 medium
題目鏈接
幾張卡牌 排成一行,每張卡牌都有一個對應的點數。
點數由整數數組 cardPoints 給出。
每次行動,你可以從行的開頭或者末尾拿一張卡牌,最終你必須正好拿 k 張卡牌。
你的點數就是你拿到手中的所有卡牌的點數之和。
給你一個整數數組 cardPoints 和整數 k,請你返回可以獲得的最大點數。
示例 1: 輸入:cardPoints = [1,2,3,4,5,6,1], k = 3 輸出:12 解釋:第一次行動,不管拿哪張牌,你的點數總是 1 。 但是,先拿最右邊的卡牌將會最大化你的可獲得點數。 最優策略是拿右邊的三張牌,最終點數為 1 + 6 + 5 = 12 。示例 2: 輸入:cardPoints = [2,2,2], k = 2 輸出:4 解釋:無論你拿起哪兩張卡牌,可獲得的點數總是 4 。示例 3: 輸入:cardPoints = [9,7,7,9,7,7,9], k = 7 輸出:55 解釋:你必須拿起所有卡牌,可以獲得的點數為所有卡牌的點數之和。示例 4: 輸入:cardPoints = [1,1000,1], k = 1 輸出:1 解釋:你無法拿到中間那張卡牌,所以可以獲得的最大點數為 1 。 示例 5: 輸入:cardPoints = [1,79,80,1,1,1,200,1], k = 3 輸出:202提示: 1 <= cardPoints.length <= 10^5 1 <= cardPoints[i] <= 10^4 1 <= k <= cardPoints.length解答:
比賽的時候差點被坑,以為是DP,一想左右各取a,b個,a+b = k 不就完了嗎
(也可以反過來想,求中間子序和最小,滑動窗口)
148 ms 44.2 MB
3. LeetCode 5394. 對角線遍歷 II medium
題目鏈接
給你一個列表 nums ,里面每一個元素都是一個整數列表。
請你依照下面各圖的規則,按順序返回 nums 中對角線上的整數。
示例 1:
示例 2:
比賽模擬寫法超時:
賽后解1:(依然超時)
實際上是按點的位置(r,c)排序:總的是r+c小的靠前,一樣的話,r 大的靠前。
class Solution { public:vector<int> findDiagonalOrder(vector<vector<int>>& nums) {int i, j;vector<vector<int>> v; //posx+posy, posx, valfor(i = 0; i < nums.size(); ++i){for(j = 0; j < nums[i].size(); ++j){v.push_back({i+j, i, nums[i][j]});}}sort(v.begin(), v.end(),[&](auto a, auto b){if(a[0]==b[0])return a[1] > b[1];return a[0] < b[0];});vector<int> ans(v.size());i = 0;for(auto& vi : v)ans[i++] = vi[2];return ans;} };估計是排序時間復雜度還是太高。
賽后解2:
- 按照兩個坐標值的和分組,存入map,內層再嵌套map(x,val)
- 外層順序遍歷(坐標和小的先),內層逆序遍歷(x大的先)
或者用數組做,參考lc題解,也是按坐標和分組,每組里面逆序寫入答案。
4. LeetCode 5180. 帶限制的子序列和 hard
題目鏈接
給你一個整數數組 nums 和一個整數 k ,請你返回 非空 子序列元素和的最大值,
子序列需要滿足:子序列中每兩個 相鄰 的整數 nums[i] 和 nums[j] ,它們在原數組中的下標 i 和 j 滿足 i < j 且 j - i <= k 。
數組的子序列定義為:將數組中的若干個數字刪除(可以刪除 0 個數字),剩下的數字按照原本的順序排布。
示例 1: 輸入:nums = [10,2,-10,5,20], k = 2 輸出:37 解釋:子序列為 [10, 2, 5, 20] 。示例 2: 輸入:nums = [-1,-2,-3], k = 1 輸出:-1 解釋:子序列必須是非空的,所以我們選擇最大的數字。示例 3: 輸入:nums = [10,-2,-10,-5,20], k = 2 輸出:23 解釋:子序列為 [10, -2, -5, 20] 。提示: 1 <= k <= nums.length <= 10^5 -10^4 <= nums[i] <= 10^4解答:
-
此題跟 LeetCode 239. 滑動窗口最大值(雙端隊列+單調棧) 非常類似,可以先看這題
-
dp[i] 表示包含 i 位置的 最大子序和
-
deque 里面保持遞減狀態(dp值遞減,實際存儲下標),距離超過 k 的,從隊頭出去
-
隊頭(最大的)>0,則 dp[i] = dp[q.front()]+nums[i],否則,dp[i] = nums[i]
-
然后檢查 dp[i] 要入隊,隊內是否單調遞減,不滿足,要pop_back()
112 ms 14.7 MB
總結
以上是生活随笔為你收集整理的LeetCode 第 186 场周赛(1060/3107,前34.1%)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: LeetCode 510. 二叉搜索树中
- 下一篇: LeetCode 1170. 比较字符串