A 每个字符最多出现两次的最长子字符串
滑动窗口:枚举窗口的左边界,尽可能右移窗口的右边界。
(当然也可以暴力枚举)
class Solution {
public:
int maximumLengthSubstring(string s) {
vector<int> cnt(26);
int res = 0;
for (int l = 0, r = -1, n = s.size();; cnt[s[l++] - 'a']--) {
while (r + 1 < n && cnt[s[r + 1] - 'a'] + 1 <= 2)
cnt[s[++r] - 'a']++;
res = max(res, r - l + 1);
if (r == n - 1)
break;
}
return res;
}
};
B 执行操作使数据元素之和大于等于 K
枚举:容易知道存在一种方案:“先通过第一种操作将数组从 [ 1 ] [1] [1] 变为 [ i ] [i] [i] ,再通过第二种操作让数组和不小于 k k k” 可以让操作数最少。枚举 i i i 以计算最小操作数
class Solution {
public:
int minOperations(int k) {
int res = INT32_MAX;
for (int i = 1; i <= k; i++)
res = min(res, i - 1 + (k - 1) / i);
return res;
}
};
C 最高频率的 ID
最大堆+哈希:用最大堆维护当前频率最高的ID,用哈希表记录各ID的最新频率
class Solution {
public:
using ll = long long;
vector<long long> mostFrequentIDs(vector<int> &nums, vector<int> &freq) {
priority_queue<pair<ll, int>> heap;//(freq,id)
unordered_map<int, ll> f;
vector<ll> res;
for (int i = 0; i < nums.size(); i++) {
f[nums[i]] += freq[i];
heap.emplace(f[nums[i]], nums[i]);
while (f[heap.top().second] != heap.top().first)
heap.pop();
res.push_back(heap.top().first);
}
return res;
}
};
D 最长公共后缀查询
字典树:遍历 wordsContainer 中的字符串,并将其按后缀插入字典树,同时更新字典树插入路径上的标记。然后遍历 wordsQuery ,在字典树上查询匹配的最长后缀的标记
class Solution {
public:
vector<int> stringIndices(vector<string> &wordsContainer, vector<string> &wordsQuery) {
trie tree;
for (int i = 0; i < wordsContainer.size(); i++)
tree.insert(wordsContainer[i], i, wordsContainer[i].size());
vector<int> res;
for (auto &q: wordsQuery)
res.push_back(tree.find(q));
return res;
}
class trie {//字典树
public:
trie *next[26];
int ind;//标记
int mn;//wordsContainer[ind]的长度
trie() {
for (int i = 0; i < 26; i++)
next[i] = nullptr;
ind = -1;
mn = 0;
}
void insert(string &s, int id, int len_i) {
trie *cur = this;
if (cur->ind == -1 || cur->mn > len_i) {//公共后缀为空的情况
cur->ind = id;
cur->mn = len_i;
}
for (auto i = s.rbegin(); i != s.rend(); i++) {
if (!cur->next[*i - 'a'])
cur->next[*i - 'a'] = new trie();
cur = cur->next[*i - 'a'];
if (cur->ind == -1 || cur->mn > len_i) {//更新标记
cur->ind = id;
cur->mn = len_i;
}
}
}
int find(string &s) {
trie *cur = this;
for (auto i = s.rbegin(); i != s.rend(); i++) {
if (!cur->next[*i - 'a'])
break;
cur = cur->next[*i - 'a'];
}
return cur->ind;
}
};
};