Frog Jump--深度遍历,动态规划--leetcode

题意:
给定一串数组,从第一个数字节点开始,向后跳跃,跳跃规则是,只能从0开始跳,最先只能跳到1,设上次跳跃步数为k,接下来可跳的步数是k,k-1,k+1,求是否能够到达最后一个数字(规定只能向后跳跃)。
eg.
[0, 1, 3, 5, 6, 8, 12, 17]
0跳k+1=1步到1,上次跳跃步数k=0
1跳k+1=2步到3,上次跳跃步数k=1
3跳k=2步到5,上次跳跃步数k=2
5跳k+1=3步到8,上次跳跃步数k=2
8跳k+1=4步到12,上次跳跃步数k=3
1跳k+1=5步到17,上次跳跃步数k=4

解法一:
用到深度遍历搜索的算法,一直递归向下搜索能够到达的点。从 第一点开始,判断向后走k-1,k,k+1步是否到达终点。没有到达的话再判断向后走k-1步是否能够到达下一节点,如果是则再继续判断判断向后走k-1,k,k+1步是否到达终点,再按步骤继续下去;没有的话再判断向后走k步是否能够到达下一节点,再按步骤继续下去。

public class FrogJumpSolution {

    public static void main(String[] args) {
        int[] stones = { 0, 1, 3, 5, 6, 8, 12, 17 };
        System.out.println(canCross(stones));
    }

    public static boolean canCross(int[] stones) {
        int i = 0, len = stones.length;
        HashSet<Integer> set = new HashSet<Integer>();
        if (len == 1) {
            if (stones[0] != 0) {
                return false;
            }
        } else if (len == 2) {
            if (stones[0] != 0 || stones[1] != 1) {
                return false;
            }
        } else {
            for (i = 0; i < len - 1; i++) {
                if (i > 2 && stones[i] * 2 <= stones[i + 1]) {
                    return false;
                }
                set.add(stones[i]);
            }
            return canReach(set, 1, 1, stones[len - 1]);
        }
        return true;
    }

    public static boolean canReach(HashSet<Integer> set, int curPos, int lastJump, int lastPos) {
        if (lastPos == curPos + lastJump + 1 || lastPos == curPos + lastJump || lastPos == curPos + lastJump - 1) {
            return true;
        }
        //先跳跃较大的步数,减少递归次数
        if (set.contains(curPos + lastJump + 1)) {
            if (canReach(set, curPos + lastJump + 1, lastJump + 1, lastPos)) {
                return true;
            }
        }
        if (set.contains(curPos + lastJump)) {
            if (canReach(set, curPos + lastJump, lastJump, lastPos)) {
                return true;
            }
        }
        //由于只能向前走,此处满足k-1向前走的条件是k>1
        if (lastJump > 1 && set.contains(curPos + lastJump - 1)) {
            if (canReach(set, curPos + lastJump - 1, lastJump - 1, lastPos)) {
                return true;
            }
        }
        return false;
    }
}

解法二:
用到动态规划的解法,用空间效率换取时间效率。用一个Hashmap存放每个节点能够跳跃的步数集合,从第一个节点开始,遍历前一个节点能够走的步数集合,计算跳跃指定可跳步数后的下个节点,判断该节点是否为最后一个节点,如果不是再计算该节点能够跳跃的步数,再进行遍历。最后,如果整个循环没有任何return遍历结束,则证明该数组不能跳跃到最后节点。

public class Solution {
    public boolean canCross(int[] stones) {
        if (stones.length == 0) {
            return true;
        }

        HashMap<Integer, HashSet<Integer>> map = new HashMap<Integer, HashSet<Integer>>(stones.length);
        map.put(0, new HashSet<Integer>());
        map.get(0).add(1);
        for (int i = 1; i < stones.length; i++) {
            map.put(stones[i], new HashSet<Integer>() );
        }

        for (int i = 0; i < stones.length - 1; i++) {
            int stone = stones[i];
            for (int step : map.get(stone)) {
                int reach = step + stone;
                if (reach == stones[stones.length - 1]) {
                    return true;
                }
                HashSet<Integer> set = map.get(reach);
                if (set != null) {
                    set.add(step);
                    if (step - 1 > 0) set.add(step - 1);
                    set.add(step + 1);
                }
            }
        }

        return false;
    }
}

猜你喜欢

转载自blog.csdn.net/yabaj/article/details/77115969