zoukankan      html  css  js  c++  java
  • Leetcode: 403. Frog Jump

    Description

    A frog is crossing a river. The river is divided into x units and at each unit there may or may not exist a stone. The frog can jump on a stone, but it must not jump into the water.
    
    Given a list of stones' positions (in units) in sorted ascending order, determine if the frog is able to cross the river by landing on the last stone. Initially, the frog is on the first stone and assume the first jump must be 1 unit.
    
    If the frog's last jump was k units, then its next jump must be either k - 1, k, or k + 1 units. Note that the frog can only jump in the forward direction.
    

    Note

    The number of stones is ≥ 2 and is < 1,100.
    Each stone's position will be a non-negative integer < 231.
    The first stone's position is always 0.
    

    Example

    [0,1,3,5,6,8,12,17]
    
    There are a total of 8 stones.
    The first stone at the 0th unit, second stone at the 1st unit,
    third stone at the 3rd unit, and so on...
    The last stone at the 17th unit.
    
    Return true. The frog can jump to the last stone by jumping 
    1 unit to the 2nd stone, then 2 units to the 3rd stone, then 
    2 units to the 4th stone, then 3 units to the 6th stone, 
    4 units to the 7th stone, and 5 units to the 8th stone.
    

    分析

    • 这道题目拿到手后,毫无思路。 仔细看下了 note 中条件限制,发现 stone 的位置范围是 [0 ~ 2^31]。无法使用状压 dp,一时陷入僵局。继续分析题目,发现对长度为 n 的 stones, 能达到的最大速度是 n+1。 这样我就可以使用二维 dp[pos][speed] 来表示一个点和速度的关系

    code

    AC 版本1: 速度上战胜 6% 的 submission, 内存上战胜了 14%的 sumission。需要优化
    class Solution(object):
        def _do(self, stones):
            n = len(stones)
            dp = [[False for _ in range(n+1)] for _ in range(n)]
            dp[0][1] = True
            for i in range(1, n):
                for j in reversed(range(0, i)):
                    dis = stones[i] - stones[j]
                    if dis > j+1:  # max speed that position j can achieve is j+1 in any input number
                        break
                    if dp[j][dis] == False:
                        continue
                    dp[i][dis] =  dp[j][dis]
                    dp[i][dis+1] =dp[j][dis]
                    dp[i][dis-1] = dp[j][dis]
            return any(dp[len(stones)-1])
    
        def do(self, hats):
            print(self._do(hats))
    
    if __name__ == '__main__':
        s = Solution()
        s.do([0,1,3,5,6,8,12,17])
        s.do([0,1,2,3,4,8,9,11])
    
    
    AC 版本2: 速度上战胜了 12% 的提交,还是很慢~
    class Solution(object):
        def canCross(self, stones):
            """
            :type stones: List[int]
            :rtype: bool
            """
            n = len(stones)
            dp = [[False for _ in range(n+1)] for _ in range(n)]
            dp[0][1] = True
            jumpedl, l2 = [0], [0]
            for i in range(1, n):
                for j in reversed(jumpedl):
                    dis = stones[i] - stones[j]
                    if dis > j+1:  # max speed that position j can achieve is j+1 in any input number
                        break
                    if dp[j][dis] == False:
                        continue
                    dp[i][dis] = dp[j][dis]
                    dp[i][dis+1] = dp[j][dis]
                    dp[i][dis-1] = dp[j][dis]
                    if l2[-1] != i:
                        l2.append(i)
                if l2[-1] != jumpedl[-1]:
                    jumpedl.append(l2[-1])
    
            return jumpedl[-1] == n-1
    
    

    总结

    • 写的几个版本虽然能 ac, 但是性能还是太低了。但是一次就 AC 通过,还是可以小小地骄傲一下
    别人 AC 的版本: 速度上是我的好几倍。 他的解题思想和我差不多,但是实现上有所不同。
    class Solution:
    	def canCross(self, stones: List[int]) -> bool:
    
    		jump = [set() for _ in range(len(stones))]
    		jump[0].add(1)
    
    		d = {}
    		for i, ele in enumerate(stones):
    			d[ele] = i
    
    		for i, ele in enumerate(stones):
    			if i == 0:
    				if stones[0] + 1 in d:
    					jump[d[stones[0] + 1]] |= set([0, 1, 2])
    			else:
    				for step in jump[i]: 
    					if step > 0 and ele + step in d:  # 采用字典查找的方式,我采用的遍历的方式。我认为这种方式过于暴力,所以没有这么用。没想到我的不太暴力的解法反而更蠢
    						jump[d[ele + step]] |= set([step + 1, step, step - 1])
    
    		return len(jump[-1]) != 0
    
    
  • 相关阅读:
    oop klass

    广义表
    Huffman树
    二叉搜索树
    二叉树的前序、中序、后序、层序遍历
    循环链表解决约瑟夫环问题
    搭建局域网SVN代码服务器
    【CheckList】精简用例,提升执行效率,减少漏测(总结篇)
    测试资源不同时,如何有针对性的设计测试用例?
  • 原文地址:https://www.cnblogs.com/tmortred/p/13191849.html
Copyright © 2011-2022 走看看