求最优解
将问题分解位若干子问题,先解子问题
1、 力扣70爬楼梯
比较基本的爬台阶问题,10级台阶每次一级或2级,爬到头。
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | |
步数 | 1 | 2 | 3 | 5 | 8 | 13 | 21 | 34 | 55 | 89 |
这里很容易理解当前爬楼梯的方法数=上一次的爬一级 + 上上一次的爬2级 , 就是上一次加上上上一次,只有这样才可以。
再来看力扣
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
class Solution {
public:
int climbStairs(int n) {
if(n<1)
{
return 0;
}
if(n==1)
{
return 1;
}
if(n==2)
{
return 2;
}
int temp1=1;
int temp2=2;
int temp;
for(int i=3;i<=n;i++)
{
temp=temp1+temp2;
temp1=temp2;
temp2=temp;
}
return temp;
}
};
力扣53最大子序和(暴力法)
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int max = INT_MIN;
int len = nums.size();
for(int i=0;i<len;i++)
{ int temp=0;
for(int j=i;j<len;j++)
{
temp+=nums[j];
if(temp>max)
{
max = temp;
}
}
}
return max;
}
};
这题如果用动态规划来做还是找关系(迭代)
从头开始前面的数据总有一个最大值,我们要找一个头绪,把前面的数组的最大值区分开来,即以i结尾的数据的最大值加上后一个与后一个值比较,去迭代计算
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int result=INT_MIN;
vector<int> temp(nums.size());
temp[0]=nums[0];
result = temp[0];
for(int i = 1;i<nums.size();i++)
{
temp[i]=max(temp[i-1]+nums[i],nums[i]);
result=max(temp[i],result);
}
return result;
}
};
贪心算法:
是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。
贪心算法与动态规划算法的主要区别:
动态规划算法中每步所作选择往往依赖于相关子问题的解,因而只有在解除相关子问题后才能做选择。
贪心算法仅当前状态做出最好选择,即局部最优选择,然后再去解做出这个选择后产生的相应子问题。
贪心算法所作的贪心选择可以依赖于以往所作过的选择,但决不依赖于将来所作的选择,也不依赖于子问题的解。正是由于这种差别,动态规划算法通常以自底向上的方式解各子问题,而贪心算法则通常以自顶向下的方式进行,以迭代的方式作出相继的贪心选择,每作一次贪心选择就将所求问题简化为一个规模更小的子问题。
对于一个具体问题,要确定它是否具有贪心选择性质,我们必须证明每一步所作的贪心选择最终导致问题的一个整体最优解。通常可以用我们在证明活动安排问题的贪心选择性质时所采用的方法来证明。首先考察问题的一个整体最优解,并证明可修改这个最优解,使其以贪心选择开始。而且作了贪心选择后,原问题简化为一个规模更小的类似子问题。然后,用数学归纳法证明,通过每一步作贪心选择,最终可得到问题的一个整体最优解。其中,证明贪心选择后的问题简化为规模更小的类似子问题的关键在于利用该问题的最优子结构性质。
动态规划的动机是消除递归过程中产生的大量重叠子问题, 两种方法 : 记忆化搜索 和 自底向上递推.
贪心法求解:
class Solution
{
public:
int maxSubArray(vector<int> &nums)
{
//类似寻找最大最小值的题目,初始值一定要定义成理论上的最小最大值
int result = INT_MIN;
int numsSize = int(nums.size());
int sum = 0;
for (int i = 0; i < numsSize; i++)
{
sum += nums[i];
result = max(result, sum);
//如果sum < 0,重新开始找子序串
if (sum < 0)
{
sum = 0;
}
}
return result;
}
};