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];
}
};