[LeetCode] 动态规划入门题目

最近接触了动态规划这个厉害的方法,还在慢慢地试着去了解这种思想,因此就在LeetCode上面找了几道比较简单的题目练了练手。

首先,动态规划是什么呢?很多人认为把它称作一种“算法”,其实我认为把它称作一种“思想”更为合适;利用动态规划去解决问题,其实就是逐步递推的过程,与贪心算法不同,动态规划递推的每一步都要求是当前的最优解(这是很重要的,递推的正确性依赖的就是这一点);利用动态规划解题时,必须自己定义出来状态和状态转移方程。然而,看上去简单,做起来却非常困难,因为解题时的具体形式千差万别,找出问题的子结构以及通过子结构重新构造最优解的过程很难统一。

经典的动态规划题目有背包问题、硬币问题等等,可以通过这些题目去理解一下这个东西。

我认为,动态规划最难的就是找出状态方程。同时,个人认为比较难的是,懂得去利用“前面每一步都是最优解”这一点。

废话不多说,直接看看LeetCode上简单的动态规划题目。

要注意的是,下面的三题都用到了局部最优和全局最优解法:

1.Jump Game

原题地址:https://leetcode.com/problems/jump-game/description/

解法:

用一个global变量保存到目前为止能跳的最远距离,用一个local变量保存当前一步出发能跳的最远距离,这题里面的状态就是走到每一步时的global[i]值,状态转移方程就是global[i] =max{nums[i] + i, global[i-1]}。当然,写代码的时候用变量代替数组即可。

class Solution {
public:
    bool canJump(vector<int>& nums) {
      int reach = 0;
      for (int i = 0; i < nums.size() - 1 && reach >= i; i++) {
          reach = nums[i] + i > reach ? nums[i] + i : reach;
      }
      return reach >= nums.size() - 1;
  }
};

2.Maximum Subarray

原题地址:https://leetcode.com/problems/maximum-subarray/description/

解法:

这一题要维护两个变量:global和local,与上面一题一样,local保存包含当前元素的最大值(局部最优),global保存的是所有情况里面的最大值(全局最优)。假设第i步的local[i]和global[i]已知,那么第i+1步的local[i + 1] = max{ nums[i] + local[i], nums[i + 1] },global[i + 1]  = max{global[i], local[i + 1]}。代码如下:

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
      int global = nums[0], local = nums[0];
      for (int i = 1; i < nums.size(); i++) {
          local = nums[i] > nums[i] + local ? nums[i] : nums[i] + local;
          global = local > global ? local : global;
      }
      return global;
  }
};

3.Best Time to Buy and Sell Stock

原题地址:https://leetcode.com/problems/best-time-to-buy-and-sell-stock/description/

这道题目有两种方法,其实都是动态规划:

(1)

class Solution {
public:
   int maxProfit(vector<int>& prices) {
       if (prices.size() == 0) return 0;
      int maxPrice = prices[prices.size() - 1];
      int res = 0;
      for (int i = prices.size() - 1; i >= 0; i--) {
          maxPrice = max(maxPrice, prices[i]);
          res = max(res, maxPrice - prices[i]);
      }
      return res;
  }
};

这种解法在这个博客里面讲得很详细:http://www.cnblogs.com/remlostime/archive/2012/11/06/2757434.html

(2)局部最优和全局最优解法:

class Solution {
public:
   int maxProfit(vector<int>& prices) {
      if (prices.size() == 0) return 0;
      int local = 0, global = 0;
      for (int i = 1; i < prices.size(); i++) {
          local = max(0, local + prices[i] - prices[i - 1]);
          global = max(local, global);
      }
      return global;
  }
};
local = max(0, local + prices[i] - prices[i - 1])这一句,我一开始在考虑:为什么不写成local = max(local, local + prices[i] - prices[i - 1])呢?后来想了一下,因为假如这样写,有可能得到的就不是包含当前元素的局部最优解了。所以,在“局部最优和全局最优解法”里面,永远不会出现local=local的情况。

这篇文章讲的都是具体题目的解法,要真正理解动态规划,真的要多做题,多找规律。
时间: 2024-10-12 04:59:51

[LeetCode] 动态规划入门题目的相关文章

leetcode中一些要用到动态规划的题目

需要仔细回顾的题目: 1.Interleaving String   交叉存取字符串 2.Decode Ways   字符串解码 3.Subsets   Subsets II          求一个集合的幂集 leetcode中一些要用到动态规划的题目,布布扣,bubuko.com

动态规划入门

通过金矿模型介绍动态规划 点击下载01背包测试数据.rar 对于动态规划,每个刚接触的人都需要一段时间来理解,特别是第一次接触的时候总是想不通为什么这种方法可行,这篇文章就是为了帮助大家理解动态规划,并通过讲解基本的01背包问题来引导读者如何去思考动态规划.本文力求通俗易懂,无异性,不让读者感到迷惑,引导读者去思考,所以如果你在阅读中发现有不通顺的地方,让你产生错误理解的地方,让你难得读懂的地方,请跟贴指出,谢谢! ----第一节----初识动态规划-------- 经典的01背包问题是这样的:

[转]很特别的一个动态规划入门教程

很特别的一个动态规划入门教程 今天在网上看到一个讲动态规划的文章,是以01背包为例的,这文章和书上的讲解非常不一样,令我眼前一亮,于是转载一下下--- (说明一下,本人非常痛恨教材公式定理漫天飞,实际的讲解却讲得非常枯涩难懂,这种中国式的教育已经延绵了几千年了,现在中国的教材还是这个样子,讲清楚 些明白些就那么难么?高中有个老师讲的一句话一直觉得很有道理:“教得会天才不是真本事,能把博士生的东西讲到小学生都会用那才是真水平.”) 附上原文地址: http://www.cnblogs.com/sd

很特别的一个动态规划入门教程

很特别的一个动态规划入门教程 (2016-03-10 17:05:48) 转载▼ 标签: cpp 动态规划 分类: Cpp精选 很特别的一个动态规划入门教程 今天在网上看到一个讲动态规划的文章,是以01背包为例的,这文章和书上的讲解非常不一样,令我眼前一亮,于是转载一下下---(说明一下,本人非常痛恨教材公式定理漫天飞,实际的讲解却讲得非常枯涩难懂,这种中国式的教育已经延绵了几千年了,现在中国的教材还是这个样子,讲清楚些明白些就那么难么?高中有个老师讲的一句话一直觉得很有道理:“教得会天才不是真

动态规划入门戳进来

学动态规划自然要从数字三角形开始起步,那么我们就先从数字三角形开始. 数字三角形题目:有一个由非负整数组成的三角形,第一行只有一个数,除了最下行之外的每个数的左下方和右下方各有一个数,如下图所示: 1 3 2 4 10 1 4 3 2 20 从第一行的数开始,每次可以往下或往右下走一格,直到走到最下行,把沿途经过的数全部加起来.如何走才能使这个和最大? 知道回溯法么(请参看:八皇后与回溯法),你会发现这是一个动态的决策问题:每次有两种选择--向左或是向右,每一步决策又影响到后面的决策,如果用贪心

由LCS到编辑距离—动态规划入门—算法学习笔记

一切计算机问题,解决方法可以归结为两类:分治和封装.分治是减层,封装是加层. 动态规划问题同样可以用这种思路,分治. 它可以划分为多个子问题解决,那这样是不是用简单的递归就完成了?也许是的,但是这样会涉及太多的不便的操作.因为子问题有重叠! 针对这种子问题有重叠的情况的解决,就是提高效率的关键. 所以动态规划问题可以总结为:最优子结构和重叠子问题. 解决这个子问题的方式的关键就是:memoization,备忘录. 动态规划算法分以下4个步骤: 描述最优解的结构 递归定义最优解的值 按自底向上的方

Leetcode动态规划【简单题】

目录 Leetcode动态规划[简单题] 53. 最大子序和 题目描述 思路分析 复杂度分析 70.爬楼梯 题目描述 思路分析 复杂度分析 121.买卖股票的最佳时机 题目描述 思路分析 复杂度分析 303.区域和检索-数组不可变 题目描述 思路分析 复杂度分析 Leetcode动态规划[简单题] 动态规划(Dynamic programming,简称DP),是一种把原问题分解为相对简单的子问题的方式求解复杂问题的方法.动态规划相较于递归,拥有更少的计算量. 53. 最大子序和 题目描述 给定一

快速上手leetcode动态规划题

快速上手leetcode动态规划题 我现在是初学的状态,在此来记录我的刷题过程,便于以后复习巩固. 我leetcode从动态规划开始刷,语言用的java. 一.了解动态规划 我上网查了一下动态规划,了解到动态规划是“带有备忘录的递归”, 而大多数用来理解动态规划的例子都是斐波那契数列,就是那个经典的递归式 f(i)=f(i-1)+f(i-2) ,f(1)=f(2)=1 那么我们就可以得到很多式子,比如求f(5): f(5)=f(4)+f(3); f(4)=f(3)+f(2); f(3)=f(2)

Leetcode 动态规划 Decode Ways

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie Decode Ways Total Accepted: 8689 Total Submissions: 55465 A message containing letters from A-Z is being encoded to numbers using the following mapping: 'A' -> 1 'B' -> 2 ... 'Z' -> 26 Given a