Jump Game 是一道有意思的题目。题意很简单,给你一个数组,数组的每个元素表示你能前进的最大步数,最开始时你在第一个元素所在的位置,之后你可以前进,问能不能到达最后一个元素位置。

比如:

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

一种走法是 0 - 2 - 3 - 4,还有一种走法是 0 - 1 - 4

O(n ^ 2) 解法


一个很显然,几乎不用动脑的解法。

设置一个布尔数组ff[0] === true 表示 index === 0 这个位置能够到达,模拟每个位置的前进,最后判断 f[lastIndex] 的值。

/**
 * @param {number[]} nums
 * @return {boolean}
 */
var canJump = function(nums) {
  var f = [];
  f[0] = true;

  nums.forEach(function(item, index, array) {
    if (f[index]) {
      var tmp = Math.min(array.length - 1, index + item)
      for (var i = index + 1; i <= tmp; i++)
        f[i] = true;
    }
  });

  return f[nums.length - 1] ? false : true;
};

但是返回了无情的TLE,给出了一组TLE的数据,数组长度达到了25000,也就是复杂度达到了O(25000 ^ 2),虽然leetcode数据普遍很弱,但是这组TLE也是让我心服口服。

解法1,跪...

O(nlogn) 解法


方法总比困难多,联想到了树状数组中的染色问题。

我们可以把jump的过程看成是染色,还是从左到右枚举位置,比如枚举到 index=0 位置时,nums[0]=5,也就是说从 index=0 的位置一直可以走到 index=5 的位置,那么我们可以把1~5这一段进行染色。当枚举到 index=1 时,如何判断能不能走到这一步呢?只需求该点被染色的次数,如果大于0,那么就是能到达,然后从该点向后继续染色,最后判断最后一点有没有被染色即可。复杂度 O(nlongn)

/**
 * @param {number[]} nums
 * @return {boolean}
 */
var sum, n;

function lowbit(x) {
  return x & (-x);
}

function update(index, val) {
  while (index) {
    sum[index] += val;
    index -= lowbit(index);
  }
}

function getAns(index) {
  var ans = 0;
  while (index <= n) {
    ans += sum[index];
    index += lowbit(index);
  }
  return ans;
}

var canJump = function(nums) {
  sum = [];
  sum[1] = 1;

  n = nums.reduce(function(pre, item, index) {
    return Math.max(pre, item + index + 1);
  }, 0);

  for (var i = 2; i <= n; i++)
    sum[i] = 0;

  for (var i = 0, len = nums.length; i < len; i++) {
    var isPainted = getAns(i + 1); // 是否被染色
    if (!isPainted) continue;
    update(i + 1 + nums[i], 1);
    update(i, -1);
  }

  return Boolean(getAns(len));
};

O(n) 解法


用树状数组显然大材小用了,树状数组可以求得被染色的次数,但是本题只需要判断是否被染色即可;而且本题每次染色都是一次。

进一步思考,我们枚举每一位时都在判断是否被染色过(从而决定是否能够到达该点且能否继续往前走),假设在某一瞬间,index=m 的位置已经被染色了,那么 index=n (n<=m) 的位置肯定已经被染色过了,我们维护一个最右边被染色的点,如果当前枚举点在该点的左侧,那么当前点已经被染色,否则即可停止遍历(因为右边的点再也不可能被染色到了)。

/**
 * @param {number[]} nums
 * @return {boolean}
 */

var canJump = function(nums) {
  var rightMost = 1;
  for (var i = 0, len = nums.length; i < len; i++) {
    if (rightMost < i + 1) break;
    rightMost = Math.max(rightMost, i + 1 + nums[i]);
  }
  return rightMost >= len;
};

Jump Game 的三种思路 - leetcode 55. Jump Game的更多相关文章

  1. Maximal Rectangle [leetcode] 的三种思路

    第一种方法是利用DP.时间复杂度是 O(m * m * n) dp(i,j):矩阵中同一行以(i,j)结尾的所有为1的最长子串长度 代码例如以下: int maximalRectangle(vecto ...

  2. [LeetCode] 55. Jump Game 跳跃游戏

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

  3. leetcode 55. Jump Game、45. Jump Game II(贪心)

    55. Jump Game 第一种方法: 只要找到一个方式可以到达,那当前位置就是可以到达的,所以可以break class Solution { public: bool canJump(vecto ...

  4. 简谈百度坐标反转至WGS84的三种思路

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 基于百度地图进行数据展示是目前项目中常见场景,但是因为百度地图 ...

  5. Java中实现十进制数转换为二进制的三种思路

    Java中实现十进制数转换为二进制 第一种:除基倒取余法 这是最符合我们平时的数学逻辑思维的,即输入一个十进制数n,每次用n除以2,把余数记下来,再用商去除以2...依次循环,直到商为0结束,把余数倒 ...

  6. Leetcode 55. Jump Game & 45. Jump Game II

    55. Jump Game Description Given an array of non-negative integers, you are initially positioned at t ...

  7. leetcode 55 Jump Game 三种方法,回溯、动态规划、贪心

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

  8. [LeetCode] 55. Jump Game 解题思路

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

  9. LeetCode 55. Jump Game (跳跃游戏)

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

随机推荐

  1. XML语言基础1

    这学期选修了XML技术这门课,没有发课本,于是参考了W3school教程,整理一下上课的内容. 1.XML简介 XML是一种标记语言,很类似HTML,它不是对HTML的替代,而是对HTML的补充.在大 ...

  2. df,du,mount

    df 查看当前系统中文件系统的使用情况 $df [-aTh]缺省选项查看当前系统的所有文件系统 -a列出所有的信息 -T列出文件系统类型 -hhuman-readable,用合适的单位表示大小 $df ...

  3. jsp html5 video实现在线视频播放源码,支持IE6,7,8,10,11,谷歌,火狐等浏览器

    jsp源码: <%@ page language="java" import="java.util.*" pageEncoding="utf-8 ...

  4. android 获取本机SMI卡号码

    //获取手机号码 TelephonyManager tm = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE); S ...

  5. Win8 忘记密码 解决办法【在E450c实测有效】

      工具/原料 已经刻录通用PE工具箱的U盘 方法/步骤 1 首先来看一下,问题产生的状况.出现登陆界面,由于密码忘记,怎么输入密码,老是提示密码错误 2 接下来,按住Shift,电脑关机重启,也就是 ...

  6. 用pygame学习初级python(二) 15.5.11

    闲得无聊,对第一版的东西做了一些修改,让它更像一个游戏,也具有一些可玩性. 项目的github地址:https://github.com/lfkdsk/BrainHole_pygame 1.人物类进行 ...

  7. Stanford机器学习笔记-6. 学习模型的评估和选择

    6. 学习模型的评估与选择 Content 6. 学习模型的评估与选择 6.1 如何调试学习算法 6.2 评估假设函数(Evaluating a hypothesis) 6.3 模型选择与训练/验证/ ...

  8. C# 格式化小总结

    C#中几个常用的格式化标识符 C或c Currency 货币格式 D或d Decimal 十进制格式(十进制整数,不要和.Net的Decimal数据类型混淆了) E或e Exponent 指数格式 F ...

  9. AC日记——字符替换 openjudge 1.7 08

    08:字符替换 总时间限制:  1000ms 内存限制:  65536kB 描述 把一个字符串中特定的字符全部用给定的字符替换,得到一个新的字符串. 输入 只有一行,由一个字符串和两个字符组成,中间用 ...

  10. Jquery:小知识;

    Jquery:小知识: jQuery学习笔记(二):this相关问题及选择器   上一节的遗留问题,关于this的相关问题,先来解决一下. this的相关问题 this指代的是什么 这个应该是比较好理 ...