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.
Your goal is to reach the last index in the minimum number of jumps.
For example:
Given array A = [2,3,1,1,4]
The minimum number of jumps to reach the last index is 2
. (Jump 1
step from index 0 to 1, then 3
steps to the last index.)
看完题目我很快就想到思路,还觉得这题一点都不hard,结果TLE了,看完真正大神的解法,才觉得自己的代码真是搓搓的。搓到不想说的算法思路,不愿意贴代码。。。
'''
@ author: wttttt at 2016.11.25
@ problem description see: https://leetcode.com/problems/jump-game-ii/
@ solution explanation see: http://blog.csdn.net/u014265088/article/details/53337157
@ github:https://github.com/wttttt-wang/leetcode
@ data_structure/deque
@ Time Limit Exceeded
time complexity can be very large when elements in nums is large.
@ another TLE solution is dp, x[i] = min(x[k]) + 1 where 0<=k= i-k
time complexity is O(N^2)
@ for better solution, see ../../greedy/45JumpGameII
'''
from collections import deque
class Solution(object):
def if_exists(self, dq, value):
'''
check that if there exists the target value
'''
for i in dq:
if i == value:
return True
return False
def jump(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
len_nums = len(nums)
if len_nums == 1:
return 0
# point_rnum = 0 # the pointer to indicate how many jumps now
point_list = 0 # the pointer to indicate
rnum = 0 # the return jump nums
list_queue = deque([0])
while list_queue != None:
x = list_queue.popleft()
for i in range(nums[x]):
y = x+i+1
if y == len_nums - 1:
return rnum+1
if self.if_exists(list_queue, y) == False:
list_queue.append(y)
if x == point_list and list_queue != None:
rnum += 1
point_list = list_queue[-1]
so = Solution()
# nums = [2,3,1,1,4]
#nums = [1,3,2,2,0,2]
nums = [1,3,2,5,1,1,2]
print so.jump(nums)
我居然是对每一个可能的位置,把该位置可能的跳到的pos记录下来(这太渣了,对大小为M的元素还不得记录M次啊,,)。这个真的很挫啊,只要nums里面的数数值比较大,肯定TLE啊。
然后想优化一下就想用dp,倒序记录每个位置到最后一个位置所需的最小跳数,时间复杂度O(N^2),实际上这个思路并不比我上面那个solution好,不过至少听起来有点算法的思想这。。。个代码我没实现,因为百度了一下发现用这个思想还是TLE- -
然后我又偷看了下tags,看到提示说用greedy,然后我一想greedy不就是每次选择当前最优解嘛,于是我就思考能不能每次都跳最大个数,然后我就马上想到了下面这种情况:
nums = [1,3,2,5,1,1,2]很明显对这种情况greedy会取到局部最优解,所以严格意义上来讲这并不是一道greddy能解的题嘛,所以我觉得leetcode给的tags很坑,以后不能偷看!!!
但是最后解法还是要用到了greedy的思想,你想虽然我们不能直接jump到最大下一跳,但是我们可以把下一跳的位置存下来。
这个解法的具体思路就是维护一个区间,区间里是当前跳数能达到的pos范围。每一跳,取区间内的元素可以跳到的最大位置+1作为下一次的区间。
具体代码如下:
'''
@ author: wttttt at 2016.11.25
@ problem description see: https://leetcode.com/problems/jump-game-ii/
@ solution explanation see: http://blog.csdn.net/u014265088/article/details/53337157
@ github:https://github.com/wttttt-wang/leetcode
@ greedy, but not restrict greedy, for that we save the interval rather than jump directly.
@ maintain an interval for each step's reach range
the interval's left edge is last interval's right edge;
the interval's right edge is the maximum pos that last interval's elements can reach.
@ time complexity: O(N), space complexity O(1)
'''
class Solution(object):
def jump(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
len_nums = len(nums)
if len_nums == 1:
return 0
'''
initialize the interval
note that right is the current interval's right edge's next element
'''
left = 0
before_right = 1
right = 1
rnum = 0 # the return num
while True:
for i in range(left,right): # iterate on current interval's elements
y = (nums[i]+i+1)
if y >=len_nums:
return rnum+1
if y > right:
right = y # find the maximum edge that the current step can reach
left = before_right
before_right = right
rnum += 1
so = Solution()
nums = [2,3,1,1,4]
#nums = [1,3,2,2,0,2]
#nums = [1,3,2,5,1,1,2]
print so.jump(nums)