一只青蛙想要過河。 假定河流被等分為?x?個單元格,并且在每一個單元格內都有可能放有一石子(也有可能沒有)。 青蛙可以跳上石頭,但是不可以跳入水中。
給定石子的位置列表(用單元格序號升序表示),?請判定青蛙能否成功過河(即能否在最后一步跳至最后一個石子上)。?開始時,?青蛙默認已站在第一個石子上,并可以假定它第一步只能跳躍一個單位(即只能從單元格1跳至單元格2)。
如果青蛙上一步跳躍了?k?個單位,那么它接下來的跳躍距離只能選擇為?k - 1、k?或?k + 1個單位。?另請注意,青蛙只能向前方(終點的方向)跳躍。
請注意:
石子的數量 ≥ 2 且?< 1100;
每一個石子的位置序號都是一個非負整數,且其 < 231;
第一個石子的位置永遠是0。
示例?1:
[0,1,3,5,6,8,12,17]
總共有8個石子。
第一個石子處于序號為0的單元格的位置, 第二個石子處于序號為1的單元格的位置,
第三個石子在序號為3的單元格的位置, 以此定義整個數組...
最后一個石子處于序號為17的單元格的位置。
返回 true。即青蛙可以成功過河,按照如下方案跳躍:?
跳1個單位到第2塊石子, 然后跳2個單位到第3塊石子, 接著?
跳2個單位到第4塊石子, 然后跳3個單位到第6塊石子,?
跳4個單位到第7塊石子, 最后,跳5個單位到第8個石子(即最后一塊石子)。
示例 2:
[0,1,2,3,4,8,9,11]
返回 false。青蛙沒有辦法過河。?
這是因為第5和第6個石子之間的間距太大,沒有可選的方案供青蛙跳躍過去。
思路:
在動態規劃方法中,我們會利用散列表map,對于散列表中的 key:value,key 表示當前石頭的位置,value 是一個包含 jumpsize 的集合,其中每個 jumpsize 代表可以通過大小為jumpysize 的一跳到達當前位置。
首先我們對散列表初始化,key 為所有石頭的位置,除了位置 0 對應的value 為包含一個值 0 的集合以外,其余都初始化為空集。接下來,依次遍歷每個位置上的石頭。對于每個currentPosition,遍歷value 中每個jumpsize,判斷位置currentPosition+newjumpsize 是否存在于map 中,對于每個 jumpsize,newjumpsize 分別為jumpsize?1,jumpsize,jumpsize+1。
如果找到了,就在對應的 value 集合里新增 newjumpsize。重復這個過程直到結束。如果在結束的時候,最后一個位置對應的集合非空,那也就意味著我們可以到達終點,如果還是空集那就意味著不能到達終點。
public class Solution {public boolean canCross(int[] stones) {HashMap<Integer, Set<Integer>> map = new HashMap<>();for (int i = 0; i < stones.length; i++) {map.put(stones[i], new HashSet<Integer>());}map.get(0).add(0);for (int i = 0; i < stones.length; i++) {for (int k : map.get(stones[i])) {for (int step = k - 1; step <= k + 1; step++) {if (step > 0 && map.containsKey(stones[i] + step)) {map.get(stones[i] + step).add(step);}}}}return map.get(stones[stones.length - 1]).size() > 0;}
}
?