- 子数组最大平均数1
给定 n 个整数,找出平均数最大且长度为 k 的连续子数组,并输出该最大平均数。
规定了长度,就简单的不像话,滑动即可
class Solution {
public:
double findMaxAverage(vector<int>& nums, int k) {
int sum = 0;
int n = nums.size();
for (int i = 0; i < k; i++) {
sum += nums[i];
}
int maxSum = sum;
for (int i = k; i < n; i++) {
sum = sum - nums[i - k] + nums[i];
maxSum = max(maxSum, sum);
}
return static_cast<double>(maxSum) / k;
}
};
- 错误的集合
请你找出重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。
先通过异或找到缺失的x和重复的y的异或,然后再根据二者异或第一个差异位进行分组,再次异或即可
class Solution {
public:
vector<int> findErrorNums(vector<int>& nums) {
int n = nums.size();
int temp = 0;
for (int num : nums) {
temp ^= num;
}
for (int i = 1; i <= n; i++) {
temp ^= i;
}
int j;
for (j = 0; j < 32; j++) {
if (temp >> j & 1 == 1) break;
}
int num1 = 0, num2 = 0;
for (int num : nums) {
if (num >> j & 1 == 1) num1 ^= num;
else num2 ^= num;
}
for (int i = 1; i <= n; i++) {
if (i >> j & 1 == 1) num1 ^= i;
else num2 ^= i;
}
for (int num : nums) {
if (num1 == num) return {
num1, num2};
}
return {
num2, num1};
}
};
- 最长数对链
给出 n 个数对。 在每一个数对中,第一个数字总是比第二个数字小。现在,我们定义一种跟随关系,当且仅当 b < c 时,数对(c, d) 才可以跟在 (a, b) 后面。我们用这种形式来构造一个数对链。给定一个数对集合,找出能够形成的最长数对链的长度。你不需要用到所有的数对,你可以以任何顺序选择其中的一些数对来构造。
按区间尾部排序后贪心即可
class Solution {
public:
int findLongestChain(vector<vector<int>>& pairs){
if(pairs.empty())return 0;
//区间排序:按右端点进行排序,若右端点不相等,按右端点由小到大进行排序;若右端点相等,则按左端点由小到大进行排序
sort(pairs.begin(),pairs.end(),[](const auto& a,const auto& b){
return (a[1]<b[1])||(a[1]==b[1]&&a[0]<b[0]);
});
//count初始化为1,用来统计不重复子区间个数的
int count=1,end=pairs[0][1];
for(const auto& p:pairs){
if(p[0]>end){
//区间不相交,需要更新边界以及不重复区间个数,注意不能有等号,即区间端点不能连续
count++;
end=p[1];
}
}
return count;
}
};
- 回文子串
给定一个字符串,你的任务是计算这个字符串中有多少个回文子串。
马拉车算法
class Solution {
public:
int countSubstrings(string s) {
int n = s.size();
string t = "$#";
for (const char &c: s) {
t += c;
t += '#';
}
n = t.size();
t += '!';
auto f = vector <int> (n);
int iMax = 0, rMax = 0, ans = 0;
for (int i = 1; i < n; ++i) {
// 初始化 f[i]
f[i] = (i <= rMax) ? min(rMax - i + 1, f[2 * iMax - i]) : 1;
// 中心拓展
while (t[i + f[i]] == t[i - f[i]]) ++f[i];
// 动态维护 iMax 和 rMax
if (i + f[i] - 1 > rMax) {
iMax = i;
rMax = i + f[i] - 1;
}
// 统计答案, 当前贡献为 (f[i] - 1) / 2 上取整
ans += (f[i] / 2);
}
return ans;
}
};
- 单词替换
现在,给定一个由许多词根组成的词典和一个句子。你需要将句子中的所有继承词用词根替换掉。如果继承词有许多可以形成它的词根,则用最短的词根替换它。
用一颗字典树即可
class Solution {
public:
struct TrieTree {
bool flag;
map<char, TrieTree*> next;
TrieTree() : flag(false) {
}
};
TrieTree* root;
Solution() {
root = new TrieTree();
}
string replaceWords(vector<string>& dict, string sentence) {
TrieTree* node;
for (auto w : dict) {
node = root;
for (auto x : w) {
if ((node->next).count(x) == 0) {
node->next[x] = new TrieTree();
}
node = node->next[x];
}
node->flag = true;
}
string res;
int start = 0;
int end = 0;
for (int i = 0; i < sentence.size(); ++i) {
if (sentence[i] == ' ')
continue;
node = root;
start = i;
while (i < sentence.size() && sentence[i] != ' ') {
if (node->flag || node->next.count(sentence[i]) == 0)
break;
node = node->next[sentence[i]];
++i;
}
end = i;
while (i < sentence.size() && sentence[i] != ' ')
++i;
if (!node->flag)
end = i;
res += sentence.substr(start, end - start) + " ";
}
if (!res.empty())
res.pop_back();
return res;
}
};
- DOTA2 参议院
假设每一位参议员都足够聪明,会为自己的政党做出最好的策略,你需要预测哪一方最终会宣布胜利并在 Dota2 游戏中决定改变。输出应该是 Radiant 或 Dire。
贪心算法依次比较队列头部并比较,大的出队后不入队,小的放在队尾,然后循环至一个队列空,则另一方获胜
class Solution {
public:
string predictPartyVictory(string senate) {
int n = senate.size();
queue<int> radiant, dire;
for (int i = 0; i < n; ++i) {
if (senate[i] == 'R') {
radiant.push(i);
}
else {
dire.push(i);
}
}
while (!radiant.empty() && !dire.empty()) {
if (radiant.front() < dire.front()) {
radiant.push(radiant.front() + n);
}
else {
dire.push(dire.front() + n);
}
radiant.pop();
dire.pop();
}
return !radiant.empty() ? "Radiant" : "Dire";
}
};
- 只有两个键的键盘
最初在一个记事本上只有一个字符 ‘A’。你每次可以对这个记事本进行两种操作:
Copy All (复制全部) : 你可以复制这个记事本中的所有字符(部分的复制是不允许的)。
Paste (粘贴) : 你可以粘贴你上一次复制的字符。
给定一个数字 n 。你需要使用最少的操作次数,在记事本中打印出恰好 n 个 ‘A’。输出能够打印出 n 个 ‘A’ 的最少操作次数。
设:dp[i]表示得到i个A所需要的操作数,则我们的目的是求dp[n]
状态转移方程:dp[i] = dp[j] + dp[i/j] (j是一个小于i的数,且能被i整除,其实就是i的因数,注意把j==1的情况排除掉)
class Solution {
public:
int minSteps(int n) {
vector<int> dp(n + 1, 0);
for (int i = 2; i <= n; i++)
{
dp[i] = i;
/* 这里的j不需要写成j <= i,因为判断j是不是因数只要检查到开平方的大小就好了,算是个小优化> */
for (int j = 2; j * j <= i; j++)
{
if (i % j == 0)
dp[i] = dp[j] + dp[i / j];
}
}
return dp[n];
}
};