LeetCode 第 199 場周賽
第4題DP有點意思
5472.重新排列字串
題目連結:5472.重新排列字串
給你一個字串 s
和一個 長度相同 的整數陣列 indices
。
請你重新排列字串 s
,其中第 i
個字元需要移動到 indices[i]
指示的位置。
返回重新排列後的字串。
示例 Sample
示例 1:
**輸入:** s = "codeleet", indices = [4,5,6,7,0,2,1,3] **輸出:** "leetcode" **解釋:** 如圖所示,"codeleet" 重新排列後變為 "leetcode" 。
示例 2:
**輸入:** s = "abc", indices = [0,1,2]
**輸出:** "abc"
**解釋:** 重新排列後,每個字元都還留在原來的位置上。
示例 3:
**輸入:** s = "aiohn", indices = [3,1,4,2,0]
**輸出:** "nihao"
示例 4:
**輸入:** s = "aaiougrt", indices = [4,0,2,6,7,3,1,5]
**輸出:** "arigatou"
示例 5:
**輸入:** s = "art", indices = [1,0,2] **輸出:** "rat"
提示:
s.length == indices.length == n
1 <= n <= 100
s
僅包含小寫英文字母。0 <= indices[i] < n
indices
的所有的值都是唯一的(也就是說,indices
是整數0
到n - 1
形成的一組排列)。
題解
class Solution { public: string restoreString(string s, vector<int>& indices) { vector<char>ans(s.length()); for(int i = 0; i < s.length(); i++) ans[indices[i]] = s[i]; s = ""; for(int i = 0; i < ans.size(); i++) s += ans[i]; return s; } };
5473.燈泡開關 IV
題目連結:5473.燈泡開關 IV
房間中有 n
個燈泡,編號從 0
到 n-1
,自左向右排成一行。最開始的時候,所有的燈泡都是 關 著的。
請你設法使得燈泡的開關狀態和 target
描述的狀態一致,其中 target[i]
等於 1
第 i
個燈泡是開著的,等於 0
意味著第 i
個燈是關著的。
有一個開關可以用於翻轉燈泡的狀態,翻轉操作定義如下:
- 選擇當前配置下的任意一個燈泡(下標為
i
) - 翻轉下標從
i
到n-1
的每個燈泡
翻轉時,如果燈泡的狀態為 0
就變為 1
,為 1
就變為 0
。
返回達成 target
描述的狀態所需的 最少 翻轉次數。
示例 Sample
示例 1:
**輸入:** target = "10111"
**輸出:** 3
**解釋:** 初始配置 "00000".
從第 3 個燈泡(下標為 2)開始翻轉 "00000" -> "00111"
從第 1 個燈泡(下標為 0)開始翻轉 "00111" -> "11000"
從第 2 個燈泡(下標為 1)開始翻轉 "11000" -> "10111"
至少需要翻轉 3 次才能達成 target 描述的狀態
示例 2:
**輸入:** target = "101"
**輸出:** 3
**解釋:** "000" -> "111" -> "100" -> "101".
示例 3:
**輸入:** target = "00000"
**輸出:** 0
示例 4:
**輸入:** target = "001011101"
**輸出:** 5
提示:
1 <= target.length <= 10^5
target[i] == '0'
或者target[i] == '1'
題解
class Solution {
public:
int minFlips(string target) {
int ans(0);
for(int i = 0, st = 0; i < target.length(); i++) {
if(target[i] - '0' == st)
continue;
st ^= 1, ans++;
}
return ans;
}
};
5474.好葉子節點對的數量
題目連結:5474.好葉子節點對的數量
給你二叉樹的根節點 root
和一個整數 distance
。
如果二叉樹中兩個 葉 節點之間的 最短路徑長度 小於或者等於 distance
,那它們就可以構成一組 好葉子節點對 。
返回樹中 好葉子節點對的數量 。
示例 Sample
示例 1:
**輸入:** root = [1,2,3,null,4], distance = 3
**輸出:** 1
**解釋:** 樹的葉節點是 3 和 4 ,它們之間的最短路徑的長度是 3 。這是唯一的好葉子節點對。
示例 2:
**輸入:** root = [1,2,3,4,5,6,7], distance = 3
**輸出:** 2
**解釋:** 好葉子節點對為 [4,5] 和 [6,7] ,最短路徑長度都是 2 。但是葉子節點對 [4,6] 不滿足要求,因為它們之間的最短路徑長度為 4 。
示例 3:
**輸入:** root = [7,1,4,6,null,5,3,null,null,null,null,null,2], distance = 3
**輸出:** 1
**解釋:** 唯一的好葉子節點對是 [2,5] 。
示例 4:
**輸入:** root = [100], distance = 1
**輸出:** 0
示例 5:
**輸入:** root = [1,1,1], distance = 2
**輸出:** 1
提示:
tree
的節點數在[1, 2^10]
範圍內。- 每個節點的值都在
[1, 100]
之間。 1 <= distance <= 10
題解
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> gao(const TreeNode* root, const int distance, int &ans) {
if(root == nullptr)
return {};
if(root->left == nullptr && root->right == nullptr) {
return {1};
}
vector<int>lch = gao(root->left, distance, ans);
vector<int>rch = gao(root->right, distance, ans);
for(int i = 0; i < min(distance, (int)lch.size()); i++) {
if(lch[i])
for(int j = 0; j < min(distance, (int)rch.size()); j++) {
if(i + j + 2 <= distance)
ans += lch[i] * rch[j];
}
}
vector<int>v(max(lch.size(), rch.size()) + 1);
for(int i = 0; i < lch.size(); i++)
v[i + 1] += lch[i];
for(int i = 0; i < rch.size(); i++)
v[i + 1] += rch[i];
return v;
}
int countPairs(TreeNode* root, int distance) {
int ans(0);
gao(root, distance, ans);
return ans;
}
};
5462.壓縮字串 II
題目連結:5462.壓縮字串 II
行程長度編碼
是一種常用的字串壓縮方法,它將連續的相同字元(重複 2 次或更多次)替換為字元和表示字元計數的數字(行程長度)。例如,用此方法壓縮字串
"aabccc"
,將 "aa"
替換為 "a2"
,"ccc"
替換為
"c3"。因此壓縮後的字串變為
"a2bc3"` 。
注意,本問題中,壓縮時沒有在單個字元後附加計數 '1'
。
給你一個字串 s
和一個整數 k
。你需要從字串 s
中刪除最多 k
個字元,以使 s
的行程長度編碼長度最小。
請你返回刪除最多 k
個字元後,s
行程長度編碼的最小長度 。
示例 Sample
示例 1:
**輸入:** s = "aaabcccd", k = 2
**輸出:** 4
**解釋:** 在不刪除任何內容的情況下,壓縮後的字串是 "a3bc3d" ,長度為 6 。最優的方案是刪除 'b' 和 'd',這樣一來,壓縮後的字串為 "a3c3" ,長度是 4 。
示例 2:
**輸入:** s = "aabbaa", k = 2
**輸出:** 2
**解釋:** 如果刪去兩個 'b' 字元,那麼壓縮後的字串是長度為 2 的 "a4" 。
示例 3:
**輸入:** s = "aaaaaaaaaaa", k = 0
**輸出:** 3
**解釋:** 由於 k 等於 0 ,不能刪去任何字元。壓縮後的字串是 "a11" ,長度為 3 。
提示:
1 <= s.length <= 100
0 <= k <= s.length
s
僅包含小寫英文字母
題解
對於前 \(i\) 個位置已經刪除 \(j\) 個,分兩類情況
- \(i\) 位置刪除,更新 \(i+1\) 位置刪除 \(j+1\) 個的解
- 不刪除,那麼貪心的儘可能保留
s[i]
,向後刪除後繼的s[l] != s[i]
,同時更新f[l][j+del]
class Solution {
public:
int getLengthOfOptimalCompression(const string s, const int m) {
const int n = s.length();
vector<vector<int>>f(n + 1, vector<int>(m + 1, 0x3f3f3f3f));
f[0][0] = 0;
for(int i = 0; i < n; ++i) {
for(int j = 0; j <= m; ++j) {
if(j + 1 <= m)
f[i + 1][j + 1] = min(f[i + 1][j + 1], f[i][j]);
for(int l = i, d = 0, c = 0; l < n; l++) {
if(s[l] != s[i])
d ++;
else
c++;
if(j + d > m)
break;
f[l + 1][j + d] = min(f[l + 1][j + d], f[i][j] + 1 + (c > 99 ? 3 : (c > 9 ? 2 : c > 1 ? 1 : 0)));
}
}
}
return f[n][m];
}
};