引言

一维动态规划根据转移方程,复杂度一般有两种情况。

func(i) 只和 func(i-1)有关,时间复杂度是O(n),这种情况下空间复杂度往往可以优化为O(1)

func(i) 和 func(1~i-1)有关,时间复杂度是O(n*n),这种情况下空间复杂度一般无法优化,依然为O(n)

本篇讨论第一种情况

例题 1

Jump Game

Given an array of non-negative integers, you are initially positioned at the first index of the array.

Each element in the array represents your maximum jump length at that position.

Determine if you are able to reach the last index.

For example:
A = [2,3,1,1,4], return true.

A = [3,2,1,0,4], return false.

class Solution {
public:
bool canJump(int A[], int n) {
}
};

这道题目肯定是用DP来做。

我一开始的想法为定义bool reachable[n] 数组,reachable[i] = true 表示第 i 元素可以到达末尾。

因此reachable[i] = if(reachable[i+1] == true || reachable[i+2] == true || ...|| reachable[i+A[i]] == true)

返回reachable[0]即为答案。

但是如果按这种思路写,需要用一个二维循环来完成整个过程,时间复杂度依然为O(n2)

按这种思路写出来的代码:

class Solution {
public:
bool canJump(int A[], int n) {
if(n <= ) return true;
bool *reachable = new bool[n-];
if(A[] >= (n-)) return true;
for(int i = n-; i >= ; --i){
if(A[i] >= (n--i)) reachable[i] = true;
else{
int j;
for(j = ; j <= A[i]; ++j){
if(reachable[i+j]){
reachable[i] = true;
break;
}
}
if(j > A[i]) reachable[i] = false;
}
}
return reachable[];
}
};

LeetCode上大数据是过不了的,超时。

网上参考了 http://blog.csdn.net/xiaozhuaixifu/article/details/13628465 的博文后,明白了上面这种思路的状态转移方程之所以效率低,是因为用bool 作为数组元素,这种思路本身就不是一个动态规划中推荐的思路。动态规划为了节省时间,往往尽可能地利用数组来存储最大量的信息,bool值只能存true和false。

改进版的思路是:这个数组不再单纯地存可达或不可达这样的bool值,而是存储从0位置出发的最大可达长度。定义数组int canStillWalk[n],canStillWalk[i]表示到达 i 位置后,依然有余力走出的最大长度。如果canStillWalk[i] < 0,表示走不到位置i。

状态转移方程为:

canStillWalk[i] = max(canStillWalk[i-1], A[i-1]) - 1;

这样我们在计算canStillWalk[i]时,就不再需要循环。

时间复杂度O(n), 空间复杂度 O(n)

class Solution {
public:
bool canJump(int A[], int n) {
if(n <= ) return true;
if(A[] >= (n-)) return true;
int *canStillWalk = new int[n];
canStillWalk[] = A[];
for(int i = ; i < n; ++i){
canStillWalk[i] = max(canStillWalk[i-], A[i-]) - ;
if(canStillWalk[i] < ) return false;
}
return canStillWalk[n-] >= ;
}
};

接着可以再简化,因为canStillWalk[i] 只和 canStillWalk[i-1]相关,那么我们就不需要定义一个数组来存放消息了,直接用pre和 cur就可以搞定,时间复杂度O(n), 空间复杂度 O(1)

class Solution {
public:
bool canJump(int A[], int n) {
if(n <= ) return true;
if(A[] >= (n-)) return true;
int pre = A[], cur = ;
for(int i = ; i < n; ++i){
cur = max(pre, A[i-]) - ;
if(cur < ) return false;
pre = cur;
}
return cur >= ;
}
};

小结

对于动态规划的题,状态转移方程比较重要,这道题的特殊性在于"步数连续",就是说,A[i] = s,表明从A[i] 可以走1~s步,而不是给定的几个不连续的值,这样我们可以通过定义最长可达距离这个转移方程来简化思想。

例题 2

Decode Ways

A message containing letters from A-Z is being encoded to numbers using the following mapping:

'A' -> 1
'B' -> 2
...
'Z' -> 26

Given an encoded message containing digits, determine the total number of ways to decode it.

For example,
Given encoded message "12", it could be decoded as "AB" (1 2) or "L" (12).

The number of ways decoding "12" is 2.

时间复杂度O(n), 空间复杂度 O(1) 解法

class Solution {
public:
int numDecodings(string s) {
if(s.empty()) return ;
int pre = -, cur = , tmp;
for(int i = ; i <= s.length(); ++i){
tmp = cur;
if(s[i-] == ''){
if(isCode(s, i-, i-)) cur = pre;
else return ;
}else if(isCode(s, i-, i-))
cur += pre;;
pre = tmp;
}
return cur;
}
private:
bool isCode(string &s, int i, int j){
if(i < ) return false;
if(s[i] >= '' || s[i] == '') return false;
if(s[i] == '' && s[j] >= '') return false;
return true;
}
};

动态规划小结 - 一维动态规划 - 时间复杂度 O(n),题 [LeetCode] Jump Game,Decode Ways的更多相关文章

  1. LeetCode总结 -- 一维动态规划篇

    这篇文章的主题是动态规划, 主要介绍LeetCode中一维动态规划的题目, 列表如下: Climbing StairsDecode WaysUnique Binary Search TreesMaxi ...

  2. Leetcode 91. Decode Ways 解码方法(动态规划,字符串处理)

    Leetcode 91. Decode Ways 解码方法(动态规划,字符串处理) 题目描述 一条报文包含字母A-Z,使用下面的字母-数字映射进行解码 'A' -> 1 'B' -> 2 ...

  3. 动态规划小结 - 二维动态规划 - 时间复杂度 O(n*n)的棋盘型,题 [LeetCode] Minimum Path Sum,Unique Paths II,Edit Distance

    引言 二维动态规划中最常见的是棋盘型二维动态规划. 即 func(i, j) 往往只和 func(i-1, j-1), func(i-1, j) 以及 func(i, j-1) 有关 这种情况下,时间 ...

  4. 动态规划小结(dynamic programming)

    动态规划在很多情况下可以降低代码的空间时间复杂度. 判断一道问题能否应用动态规划,需要关注问题是否具有最优子结构,当前规模的问题的解在之前问题的解里面,还要注意的是要满足无后效性的原则.随后就是寻找递 ...

  5. HDU 4502 吉哥系列故事——临时工计划(一维动态规划)

    题意:吉哥的假期是1到n天,然后有m个工作可以让吉哥选择做,每个工作都有一个开始 t_s  和结束的时间   t_e ,都用天来表示,然后每个工作必须从第一天做到最后一天, 从头到尾做完之后就可以得到 ...

  6. leetcode 940. 不同的子序列 II (动态规划 ,字符串, hash,好题)

    题目链接 https://leetcode-cn.com/problems/distinct-subsequences-ii/ 题意: 给定一个字符串,判断里面不相同的子串的总个数 思路: 非常巧妙的 ...

  7. 【2】【典型一维动态规划】【剑指offer+leetcode53】连续子数组的最大和

    HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学.今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决.但是,如果向量中包含负数 ...

  8. 每日一题 LeetCode 486. 预测赢家 【递推】【前缀和】【动态规划】

    题目链接 https://leetcode-cn.com/problems/predict-the-winner/ 题目说明 题解 主要方法:递推:动态规划:前缀和 解释说明: 求前缀和 pre_nu ...

  9. 每日一题 LeetCode 491. 递增子序列 【递推】【递增子序列】【动态规划】

    题目链接 https://leetcode-cn.com/problems/increasing-subsequences/ 题目说明 题解 主要方法:递推:动态规划 解释说明: 数据表示:观察数据范 ...

随机推荐

  1. Fluent Python: Mutable Types as Parameter Defaults: Bad Idea

    在Fluent Python一书第八章有一个示例,未看书以先很难理解这个示例运行的结果,我们先看结果,然后再分析问题原因: 定义了如下Bus类: class Bus: def __init__(sel ...

  2. Comparison of Android versions(strcmp的应用)

    Description As an Android developer, itˇs really not easy to figure out a newer version of two kerne ...

  3. c# byte[] 保存图片

    1.用函数即可,File.WriteAllBytes(@"E:\123.bmp", pcBMPBuffer); 2.byte[]也可和image互相转化.

  4. c# 删除word文档中某一页

    object objPage = 14; int pages = oDoc.ComputeStatistics(Microsoft.Office.Interop.Word.WdStatistic.wd ...

  5. Zigbee安全基础篇Part.2

    原文地址: https://www.4hou.com/wireless/14252.html 导语:本文将会探讨ZigBee标准提供的安全模型,用于安全通信的各种密钥.ZigBee建议的密钥管理方法以 ...

  6. 第一次通过CLR Profile解决内存占用过高的问题

    炮哥:"嘿,哥们,忙啥呢,电脑卡成这逼样." 勇哥:"在用CLR Profile工具分析下FlexiPrint的内存占用情况." 炮哥:“哎哟,不错啊,玩高级的 ...

  7. E2202 Required package 'rtl' not found"

    最近重新下载了一个delphi Berlin 10.1.2绿色版本,解压后剪切到别的盘上了,一些需要直接编译的.dpk包,例如fastReport都不能了,都提示E2202 Required pack ...

  8. ueditor 定制工具栏图标

    在使用Ueditor时,如要简化工具栏上的按钮,可以修改配置项的方法: 1. 方法一:修改 ueditor.config.js 里面的 toolbars 2. 方法二:实例化编辑器的时候传入 tool ...

  9. 移动端body跟着模态框一起滑动问题

    遇到了一个问题,是点击链接出现弹框,弹框里面的内容是可以滑动的,结果我滑动的时候发现下面的body也跟着一起滑动,先看一下代码. 弹框的 HTML: <div class="mask& ...

  10. Axure RP 的安装与卸载

    官网:http://www.axure.com/download 支持Windows和Mac