某不知名学校算法课第三次实验报告
题目来自力扣 这次实验是贪心算法
贪心的思维很跳跃,每道题也没有固定的模板的思考方向
跳跃游戏
题目描述:
我们把数组中的每个元素看作是最大覆盖范围,当覆盖范围到达终点时,即满足题目条件
以样例1为例 初始指向2 覆盖范围为231,更新至3 覆盖范围3114 到达终点 符合题意
以样例2为例 初始指向3 覆盖范围3210 指向2 覆盖范围210 指向1 覆盖范围10 指向0 覆盖范围0
可以看到 我们没有办法覆盖到终点4 所以不符合题意
代码加注释如下:
class Solution {
public:
bool canJump(vector<int>& nums) {
int cover = 0;
for(int i = 0; i <= cover; i ++ )
{
//不断更新自己的覆盖范围
cover = max(cover, nums[i] + i);
//如果覆盖范围能到达终点
if(cover >= nums.size() - 1) return true;
}
return false;
}
};
很短,但是很需要思维,这就是贪心 也是传说中的局部最优解到全局最优解
分割平衡字符串
题目描述:
这道题可以暴力 数据不大 但是感觉这种查询匹配问题 用哈希表的方式解决是通常的选择
计数L 发现R计数相等时 就是一对平衡字串 思路很简单
代码如下:
class Solution {
public:
int balancedStringSplit(string s) {
int cnt = 0; //记录L R的数量关系
int res = 0;
for(char c : s) // 遍历
{
if( c == 'L' ) cnt ++ ;
else cnt --;
if( cnt == 0 ) res ++ ;
}
return res;
}
};
用户分组
从题目中,我们知道要填入的数据是0 ~n-1的连续整数,也正好对应了数组的下标
然后给的函数要返回双层vector,也就是说我们得要一个单层vector填入
跟上一题差不多,也是用一个类似哈希表的写法,进行查询和匹配的问题
代码+注释如下:
class Solution {
public:
vector<vector<int>> groupThePeople(vector<int>& groupSizes) {
vector<vector<int>> res;
//二维vector只能用一级vector去push——back
unordered_map<int , vector<int>>M; //哈希表
int cnt = 0; // 记录数组下标 正好是0~n-1号数字
for(auto x : groupSizes) //强化for循环
{
M[x].push_back(cnt);
//该组存满了
if(M[x].size() >= x)
{
//存入答案
res.push_back(M[x]);
//同时清空
M[x].clear();
}
cnt ++;
}
return res;
}
};
非递增顺序的最小子序列
题目描述:
简单贪心题,我们先进行一遍排序,从最大的数字开始选,选到答案集合中的数的和大于剩下的数的和即可
代码+注释如下:
class Solution {
public:
vector<int> minSubsequence(vector<int>& nums) {
vector<int> res; // 存答案 返回值是vector
sort(nums.begin(),nums.end()); // 排序
int sum = 0, cur = 0, idx = nums.size() - 1;
for(int i : nums) sum += i;
while(cur <= sum) //答案序列和小于剩余序列和
{
sum -= nums[idx];
cur += nums[idx];
res.push_back(nums[idx--]); // 加入答案序列 顺便往前选择
}
return res;
}
};