zoukankan      html  css  js  c++  java
  • [LeetCode#45]Jump Game II

    Problem:

    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.)

    Anaslysis:

    This is also a dynamic problem. It reminds you there could be good and bad dynamic algorithm. Once you feel like something was repeatedly done. Yous should try a better solution to solve it.
    
    Solution 1:
    This idea is instant, and suitable for my thinking habit, but it is really not efficient.
    Basic idea:
    Use a array to record the minimum steps required to reach a element. 
    Then we use following function to update on it.
    -------------------------------------------------------------
    for (int j = 1; j <= nums[i]; j++) {
        if (i+j < len) {
            nums[i+j] = Math.min(nums[i]+1, nums[i+j]);
        }
    }
    -------------------------------------------------------------

    Solution 1:

    public class Solution {
        public int jump(int[] nums) {
            if (nums == null)
                throw new IllegalArgumentException("nums is null!");
            int len = nums.length;
            if (len <= 1)
                return 0;
            int[] min = new int[len];
            Arrays.fill(min, Integer.MAX_VALUE);
            min[0] = 0;
            for (int i = 0; i < len; i++) {
                for (int j = 1; j <= nums[i]; j++) {
                    if (i+j < len) {
                        min[i+j] = Math.min(min[i]+1, min[i+j]);
                    }
                }
            }
            return min[len - 1];
        }
    }

    Upgraded analysis:

    Time Limit Exceeded
    
    Even the idea of above solution is right, but there are repeates in computing. 
    We know: iff i < j, the steps to reach i must no greater than j. step[i] <= step[j]
    Reason: once we could reach step[j], we must be able to reach step[i] (just fewer steps)
    
    Thus if we have already reached step[j] from step[i], we should we test iff we could use step[i+1] to reach step[j]. The only thing we should take care, iff step[i+1] could help us to reach further elements!
    
    The update solution:
    We should two window for this problem, 
    latest reach: the maximum element we could reach from previous window's elements.(previous step)
    reach: the maimum element we could reach from current window. (current step)
        {[1]},  {[2]},  { [1]   [3] },    {[2]  [4]     [5]} 
        0       1       2       3           4   5       6
    For example: at step 0, our latest reach is 0 (the current element), after scan the [1] element in the window, the reach becomes 1, which means we can reach element nums[1]. 
    
    We Keep the above invariant to update our next reach window throw latest reach window(current). 
    reach = Math.max(reach, nums[i] + i);
    
    But reach is for next window, once we enter the elements at reach window, it means we have to use one step to achieve it. Thus we have following code for this purpose.
    for (int i = 0; i <= reach && i < len; i++) {
        if (i > last_reach) {
            step ++;
            last_reach = reach;
        }
    ...
    }
    Note: we count the step, only when we need to enter the window. (reach nums[i])
    Also Note: the checking codition for the for loop, if i exceed the maximum range of reach, it means there is no path. We should stop at here.

    Solution 2:

    public class Solution {
        public int jump(int[] nums) {
            if (nums == null)
                throw new IllegalArgumentException("nums is null!");
            int len = nums.length;
            if (len <= 1)
                return 0;
            int last_reach = 0;
            int step = 0;
            int reach = 0;
            for (int i = 0; i <= reach && i < len; i++) {
                if (i > last_reach) {
                    step ++;
                    last_reach = reach;
                }
                reach = Math.max(reach, nums[i] + i);
            }
            return (reach >= nums.length - 1) ? step : 0;
        }
    }
  • 相关阅读:
    ios代码大全
    MYSQL数据库之如何在已经建立好表之后重构数据表
    关于cookie在一个页面设置但是在另外一个页面获取不到的原因
    cookie的那点事儿
    关于a标签不能调用js方法的小细节,你注意到了么?
    关于mysql预处理技术的一点小心得
    关于delete使用limit的一些注意事项
    DP1 等分连续1-N个数的划分种数
    Spring 编程式事务和声明式事务管理
    java https client信任所有证书
  • 原文地址:https://www.cnblogs.com/airwindow/p/4787846.html
Copyright © 2011-2022 走看看