代码随想录刷题60Day
目录
贪心算法概述
贪心算法(Greedy algorithm)是一种常用的算法设计方法,它在每一步选择中都采取当前状态下最优的选择,希望通过局部最优选择最终达到全局最优。贪心算法通常适用于满足最优子结构(即问题的最优解包含子问题的最优解)和贪心选择性质(即每一步的最优选择不依赖于后面的选择)的问题。
贪心算法的基本思路是通过不断地做出局部最优选择,进而得到全局最优解。具体而言,贪心算法的步骤如下:
1)确定问题的最优子结构:贪心算法必须满足问题的最优解包含子问题的最优解,即通过局部最优选择可以得到全局最优解。
2)制定贪心选择策略:根据当前状态下的局部信息,确定最优的选择。这个选择应该是符合问题要求的,并且能够使问题规模缩小。
3) 解决子问题:根据贪心选择策略,将原问题转化为一个规模更小的子问题,并继续求解子问题。
4) 合并子问题的解:将子问题的解合并起来,得到原问题的解。
5)检查解的有效性:检查贪心算法得到的解是否满足问题的约束条件和要求。
贪心算法算法这种局部最优即为全局最优的解决方法并不是适用于所有问题。在某些情况下,某些特殊解必须要从全局考虑,由此使得局部最优并不能推导出全局最优。因此,在应用贪心算法时,需要仔细分析问题的性质,确保贪心选择策略的正确性。
总而言之,贪心算法是一种简单而高效的算法设计方法,通过每一步的局部最优选择,逐步求解问。
贪心算法的一些简单应用
贪心算法常会被用来解决一些采用数组进行数据存储的问题,而在数组相关问题时,我们常会采用双指针来辅助解题。因此在下面问题给出的解答中,也常看见双指针的影子。
分发饼干
int findContentChildren(vector<int>& g, vector<int>& s)
{
int result = 0;
if (s.empty())return result;
sort(g.begin(), g.end());
sort(s.begin(), s.end());
for (int i = 0, j = 0; i < g.size() && j < s.size(); j++)
{
if (g[i] <= s[j])
{
i++;
result++;
}
}
return result;
}
摆动序列
int wiggleMaxLength(vector<int>& nums)
{
if (nums.size() < 2)return nums.size();
int p = 1;
while (p < nums.size() && nums[0] == nums[p])p++;
if (p == nums.size())return 1;
//特殊情况处理(当全部元素相同时,长度为1。顺便首元素去重)
int result = 2;
for (int i = p, j = p; j < nums.size() - 1; j++)
{//快慢指针法
if ((nums[i - 1] < nums[i] && nums[j] > nums[j + 1]) ||
(nums[i - 1] > nums[i] && nums[j] < nums[j + 1]))
{
result++;
i = j + 1;//更新慢指针
}
}
return result;
}
int wiggleMaxLength2(vector<int>& nums)
{
int result = 1;
int flag = 0;
for (int i = 1; i < nums.size(); i++)
{
if (nums[i - 1] < nums[i] && (flag == 0 || flag == 1))
{
result++;
flag = -1;
}
else if (nums[i - 1] > nums[i] && (flag == 0 || flag == -1))
{
result++;
flag = 1;
}
}
return result;
}
最大子数组和
int maxSubArray(vector<int>& nums)
{
int result = nums[0];
for (int sum = nums[0], i = 1; i < nums.size(); i++)
{
if (sum < 0)sum = nums[i];
else sum += nums[i];
result = result > sum ? result : sum;
}
return result;
}