leetcode55 jumpGame贪心算法

上题目:

  解空间明确,一个从 nums[0] 开始辐射出去的树状解空间。首先暴力搜索一下,暴力搜索解法:

    public final boolean canJump(int[] nums) {
        if(nums==null){return false;}
        int length=nums.length;
        return jump(nums,length,0);
    }

    public final boolean jump(int[] nums,int length,int current){
        if(current==length-1){
            return true;
        }
        if(current>length-1){
            return false;
        }
        boolean re=false;
        int currentSteps=nums[current];
        for(int i=1;i<=currentSteps;i++){
            re=re||jump(nums,length,current+i);
        }
        return re;
    }

  解的过程中我们发现,回归过程是自底向上的,在回归的过程中,有大量的节点出现了重复计算,可考虑缓存避免重复计算。缓存搜索:

    public final boolean canJump(int[] nums) {
        if(nums==null){return false;}
        int length=nums.length;
        int[] cache=new int[length];
        return jump(nums,length,0,cache);
    }

    public final boolean jump(int[] nums,int length,int current,int[] cache){
        if(current==length-1||cache[current]==1){return true;}
        if(current>length-1||cache[current]==-1){return false;}
        boolean re=false;
        int currentSteps=nums[current];
        for(int i=1;i<=currentSteps;i++){
            if(jump(nums,length,current+i,cache)){
                re=true;
                break;
            }
        }
        cache[current]=re?1:-1;
        return re;
    }

  缓存计算定义好后,考虑避免递归带来的栈帧释放创建的开销,逆推缓存优化为动态规划解法:

    public final boolean dpJump1(int[] nums) {
        if (nums == null) {
            return false;
        }
        int length = nums.length;
        int[] cache = new int[length];
        int goodNode = 0;
        for (int i = length - 1; i >= 0; i--) {
            int currentStep = nums[i];
            if (currentStep + i >= (length - 1)) {
                goodNode = i;
                cache[i] = 1;
                continue;
            }
            for (int j = i + currentStep; j >= i; j--) {
                if (cache[j] == 1) {
                    cache[i] = 1;
                    break;
                }
            }
            printNums(cache);
        }
        return cache[0] == 1 ? true : false;
    }

  动态规划的过程中牵扯到两层 for 循环,内层的 for 循环可以使用贪心算法优化,以局部最优解获得全局最优解,我们只需要找到互动范围内最近的可到达终点的 goodNode 就可以了。贪心算法:

    //贪心
    public final boolean dpJump(int[] nums) {
        if (nums == null) {
            return false;
        }
        int length = nums.length;
        int[] cache = new int[length];
        int goodNode = 0;
        for (int i = length - 1; i >= 0; i--) {
            int currentStep = nums[i];
            if (currentStep + i >= (length - 1)) {
                goodNode = i;
                cache[i] = 1;
                continue;
            }
            if (goodNode != 0 && (i + currentStep) >= goodNode) {
                goodNode = i;
                cache[i] = 1;
            }
            printNums(cache);
        }
        return cache[0] == 1 ? true : false;
    }
原文地址:https://www.cnblogs.com/niuyourou/p/12643634.html