From 73701020a37a13a4e4af9f576db5cc5ab706a71f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=94=90=E6=A0=91=E6=A3=AE?= Date: Thu, 17 Jan 2019 23:27:55 +0800 Subject: [PATCH] Create 55. Jump Game.md --- solutions/55. Jump Game.md | 56 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 solutions/55. Jump Game.md diff --git a/solutions/55. Jump Game.md b/solutions/55. Jump Game.md new file mode 100644 index 0000000..cf2f71f --- /dev/null +++ b/solutions/55. Jump Game.md @@ -0,0 +1,56 @@ +# [55. Jump Game](https://leetcode.com/problems/jump-game/) +# 思路 +给定一个非负数组成的数组,每个元素代表从当前位置能向前跳的最大步数,初始位置为第一个元素,问能否到达最后一个元素。 + +## 思路一、动态规划 +开辟一个和nums同样大小的数组can_reach,其代表的意思是: 若`can_reach[i]==1`说明从位置i可以到达最后一个位置,若`can_reach[i]==0`则说明不能到达。 +所以最后的返回结果就是`can_reach[0]`。 +那我们该怎样求`can_reach[i]`呢? 我们知道从位置i能到达的最远位置是`i+nums[i]`,所以我们只需要看在这个区间内是否有满足能到达的就可以了,即若存在 +j属于[i+1, i+nums[i]],使得`can_reach[j]`为1,那么`can_reach[i]=1`,否则`can_reach[i]=0`。 +所以我们应该从后往前算can_reach。 + +若nums中所有元素都为0,则是最坏情况,此时得出时间复杂度为O(n^2),空间复杂度为O(n)。 + +## 思路二、贪心 +思路一的时间复杂度比较高,仔细分析题目可得出更快的解法。 +其实我们用贪心就可以解决此问题,从后往前遍历数组nums,用d记录直到此时能到达的最远的位置。假设此时遍历到了位置i,如果出现了`d < i`说明根本到达不了位置i,更别说到达 +最后一个位置了,所以直接返回false即可;若`d >= n - 1`说明此时就可以到达最后一个位置了,所以直接返回true即可;否则更新d: `d = max(d, i + nums[i])`。 + +这种方法最多只遍历了一遍数组,所以时间复杂度为O(n),空间复杂度显然为O(1)。 + +# C++ +## 思路一 +``` C++ +class Solution { +public: + bool canJump(vector& nums){ + int n = nums.size(); + int can_reach[n] = {0}; + can_reach[n - 1] = 1; + for(int i = n - 2; i >= 0; i--) + for(int j = 1; j <= nums[i]; j++) + if(can_reach[i + j]){ + can_reach[i] = 1; + break; + } + + return can_reach[0] == 1; + } +}; +``` +## 思路二 +``` C++ +class Solution { +public: + bool canJump(vector& nums){ + int n = nums.size(); + int d = 0; + for(int i = 0; i < n; i++){ + if(d < i) return false; + if(d >= n - 1) return true; + d = max(d, i + nums[i]); + } + return false; + } +}; +```