Leetcode 1201-1300
1233. Remove Sub-Folders from the Filesystem (Medium)¶
一些文件目录,去除其中的子路径,输出最后结果
Input: folder = ["/a","/a/b","/c/d","/c/d/e","/c/f"] Output: ["/a","/c/d","/c/f"] Explanation: Folders "/a/b/" is a subfolder of "/a" and "/c/d/e" is inside of folder "/c/d" in our filesystem.
思路
将字符串排序,保证一个子路径的父路径一定在其前面,然后将前面非子路径的路径都插入一个unordered_set
,然后遍历这个字符串,判断是否在其中即可
vector<string> removeSubfolders(vector<string>& folder) {
sort(folder.begin(), folder.end(), [](const string& a, const string& b) {
return a.size() < b.size();
});
unordered_set<string> dict;
vector<string> res;
for (string& s : folder) {
bool sub = false;
for (int i = 0; i < s.size(); i++) {
if (s[i] == '/' && dict.count(s.substr(0, i))) {
sub = true;
break;
}
}
if (!sub) {
res.push_back(s);
dict.insert(s);
}
}
return res;
}
1234. Replace the Substring for Balanced String (Medium)¶
一个由
Q
,W
,E
和R
组成的字符串,替换其中一段字符串,变成四种字符数量相等的字符串,问替换字符串的最小长度字符串长度一定是4的整数倍
Input: s = "QQQW" Output: 2 Explanation: We can replace the first "QQ" to "ER".
思路
这里其实滑动窗口即可,窗口大小是可以贪心的,思路就是选窗口开始位置,同时窗口结尾尽量靠前,即直到有元素超过size/4为止
滑动一遍即可得到答案
int balancedString(string s) {
int limit = s.size() / 4;
vector<int> cnt(26, 0);
int r = s.size() - 1;
while (r >= 0 && cnt[s[r] - 'A'] < limit) cnt[s[r--] - 'A']++;
if (r < 0) return 0;
int res = r + 1;
for (int i = 0; i <= s.size(); i++) {
cnt[s[i] - 'A']++;
while (r < s.size() - 1 && cnt[s[i] - 'A'] > limit) cnt[s[++r] - 'A']--;
if (cnt[s[i] - 'A'] > limit) break;
res = min(res, r - i);
}
return res;
}
1235. Maximum Profit in Job Scheduling (Hard)¶
有若干任务,每个任务有一个开始时间和结束时间,以及一个收益,求所能达到的最大收益。结束时间和开始时间相邻的两个任务可以先后执行
Input: startTime = [1,2,3,3], endTime = [3,4,5,6], profit = [50,10,40,70] Output: 120 Explanation: The subset chosen is the first and fourth job. Time range [1-3]+[3-6] , we get profit of 120 = 50 + 70.
思路
基本思路是动归,即确定到一个时间点为止所能获得的最大收益,接着将任务以结束时间排序,这个任务的收益加上这个任务开始时间的最大收益加起来,即可以完成一次对任务的更新
这里找每个任务开始时间的最大收益,可以直接进行二分搜索,第一次写的时候事先进行了排序加离散化,但这样其实复杂度更高,因为二分搜索的长度其实是从小到大的,所以相对一开始将所有时间点放在一起再进行排序,常数复杂度更低
int jobScheduling(vector<int>& startTime, vector<int>& endTime, vector<int>& profit) {
vector<pair<int, int>> jobs;
for (int i = 0; i < endTime.size(); i++) jobs.push_back({ endTime[i], i });
sort(jobs.begin(), jobs.end());
vector<int> dp(jobs.size(), 0);
for (int i = 0; i < dp.size(); i++) {
if (i == 0) dp[i] = profit[jobs[i].second];
else {
dp[i] = dp[i - 1];
int time = startTime[jobs[i].second];
int rank = upper_bound(jobs.begin(), jobs.end(), time, [](int t, const pair<int, int>& job) {
return t < job.first;
}) - jobs.begin() - 1;
int prev = 0;
if (rank >= 0) prev = dp[rank];
dp[i] = max(dp[i], prev + profit[jobs[i].second]);
}
}
return dp.back();
}
1238. Circular Permutation in Binary Representation (Medium)¶
给出两个整数
n
和start
,要求给出在[0, 2^n]
范围内,以start
开始的一个序列,每两个数之间只有一个bit的差别
- 1 <= n <= 16
- 0 <= start < 2 ^ n
思路
先生成格雷码,gray(i)=i^(i>>1)
,然后找到哪个格雷码是start
,从这位开始重新整理结果即可
vector<int> circularPermutation(int n, int start) {
int length = (1 << n);
vector<int> gray(length, 0), result(length, 0);
int index = 0;
for (int i = 0; i < length; i++) {
gray[i] = i ^ (i >> 1);
if (gray[i] == start) index = i;
}
for (int i = 0; i < length; i++) result[i] = gray[(i + index) % length];
return result;
}
1239. Maximum Length of a Concatenated String with Unique Characters (Medium)¶
给一个字符串列表,求由这些字符串能组成的没有重复字母的最长字符串长度,字符串只包含小写字母
+ 1 <= arr.length <= 16 + 1 <= arr[i].length <= 26Input: arr = ["cha","r","act","ers"] Output: 6 Explanation: Possible solutions are "chaers" and "acters".
思路
一共26个字母,可以用一个int来表示每个字符串含有的字母,然后进行深搜遍历即可,这里注意如果一个字符串包含重复字母,那么这个字符串不应该被加进来
小技巧是在得到每个字符串对应整数后,可以不用字符串数组,最后统计所得结果int中有多少位1即可,用__builtin_popcount
即可实现
另外需要注意的是,用递归写比自己用deque
来模拟要快得多
void dfs(const vector<int>& nums, int i, int num, int& result) {
if (i == nums.size()) {
result = max(result, __builtin_popcount(num));
return;
}
dfs(nums, i + 1, num, result);
if ((num & nums[i]) == 0)
dfs(nums, i + 1, num | nums[i], result);
}
int maxLength(vector<string>& arr) {
vector<int> nums;
for (auto& str : arr) {
int num = 0, add = 1;
for (char c : str) {
int d = (c - 'a');
if ((num >> d) & 1 > 0) {
add = 0;
break;
} else
num |= (1 << d);
}
if (add) nums.push_back(num);
}
int result = 0;
dfs(nums, 0, 0, result);
return result;
}