题目
-
仅执行一次字符串交换能否使两个字符串相等
-
找出星型图的中心节点
-
最大平均通过率
-
好子数组的最大分数
思路与算法
- 仅执行一次字符串交换能否使两个字符串相等
翻译题目即可 - 找出星型图的中心节点
关键在于清楚这个中心点出现的次数刚好就是点数-1 - 最大平均通过率
优先队列存所有的最大通过率,注意加一个同学到一个班里的通过率提升最大,再加就会减少通过率,因此每次只能加1个,按顺序一个一个加才行。 - 好子数组的最大分数
贪心,尽可能宽的范围,尽可能大的最小值。最小值包含k,依次减小遍历即可。
代码实现
- 仅执行一次字符串交换能否使两个字符串相等
class Solution {
public:
bool areAlmostEqual(string s1, string s2) {
if (s1.size() != s2.size()) {
return false;
}
if (s1 == s2) {
return true;
}
for (int i = 0; i < s1.size() - 1; ++i) {
for (int j = i + 1; j < s1.size(); ++j) {
if (swap(s1,i,j) == s2) {
return true;
}
}
}
return false;
}
public:
string swap (string s,int a,int b) {
char tmp = s[b];
s[b] = s[a];
s[a] = tmp;
return s;
}
};
- 找出星型图的中心节点
class Solution {
public:
int findCenter(vector<vector<int>>& edges) {
// 中心点出现的次数就是二维数组的行数,每一行都有一个中心点
// 注意下面这个target == 点数n - 1,
int target = edges.size();
int res = 0;
vector<int> cnt(target + 2,0);
for (auto edge : edges) {
++cnt[edge[0]];
++cnt[edge[1]];
}
// 索引范围为1 - target+2,因此直接遍历cnt,找到那个等于行数的索引输出即可。
for (int i = 1; i < target + 2; ++i) {
if (cnt[i] == target) {
return i;
}
}
return -1;
}
};
- 最大平均通过率
class Solution {
public:
double maxAverageRatio(vector<vector<int>>& classes, int extraStudents) {
// 优先队列pq
priority_queue<pair<double, int>> h;
// 将加入一个好学生增加的通过率提升值和对应的插入的班级索引放入pq
for (int i = 0; i < classes.size(); ++i)
h.push( pair((classes[i][0] + 1) / (classes[i][1] + 1.0) - classes[i][0] / (double)classes[i][1], i ) );
// 每次插班一个好学生,一个一个按照通过率提升来排序再插入进去,最后得到最大结果
while (extraStudents--) {
// 最大提升的二元组保存
pair<double, int> cur = h.top();
// 将其出队
h.pop();
// 对应的班级人数和通过人数都增加1
++classes[cur.second][0];
++classes[cur.second][1];
// 再加入一个通过率提升进去。
h.push({
(classes[cur.second][0] + 1) / (classes[cur.second][1] + 1.0) - classes[cur.second][0] / (double)classes[cur.second][1], cur.second});
}
// 计算结果并输出
double ans = 0;
for (auto i : classes) ans += i[0] / (double)i[1];
return ans / classes.size();
}
};
- 好子数组的最大分数
class Solution {
public:
int maximumScore(vector<int>& nums, int k) {
// 暴力遍历即可
int left = k, right = k;
int ans = 0;
// 从nums[k]开始遍历
for (int i = nums[k]; i >= 1; i--) {
// 左右开始移动贪心
while (left > 0 && nums[left - 1] >= i) {
left--;
}
while (right < (nums.size() - 1) && nums[right + 1] >= i) {
right++;
}
// 更新最大值
ans = max(ans,(right - left + 1) * i);
}
return ans;
}
};
写在最后
- 合理安排时间宝贝