[Swift]LeetCode403. 青蛙過河 | Frog Jump

原文地址:http://www.javashuo.com/article/p-wcwtttaq-g.html html

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

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

Note:this

  • 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 1:spa

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

Example 2:code

[0,1,2,3,4,8,9,11]

Return false. There is no way to jump to the last stone as 
the gap between the 5th and 6th stone is too large.

一隻青蛙想要過河。 假定河流被等分爲 x 個單元格,而且在每個單元格內都有可能放有一石子(也有可能沒有)。 青蛙能夠跳上石頭,可是不能夠跳入水中。htm

給定石子的位置列表(用單元格序號升序表示), 請斷定青蛙可否成功過河(即可否在最後一步跳至最後一個石子上)。 開始時, 青蛙默認已站在第一個石子上,並能夠假定它第一步只能跳躍一個單位(即只能從單元格1跳至單元格2)。blog

若是青蛙上一步跳躍了 個單位,那麼它接下來的跳躍距離只能選擇爲 k - 1或 k + 1個單位。 另請注意,青蛙只能向前方(終點的方向)跳躍。three

請注意:

  • 石子的數量 ≥ 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個石子之間的間距太大,沒有可選的方案供青蛙跳躍過去。

64ms
 1 class Solution {
 2     func canCross(_ stones: [Int]) -> Bool {
 3         if stones.count == 0 {
 4             return false
 5         }
 6         let n = stones.count
 7         if n == 1 {
 8             return true
 9         }
10         if stones[1] != 1 {
11             return false
12         }
13         if n == 2 {
14             return true
15         }
16         let last = stones.last!
17         var hs = Set<Int>()
18         for i in 0..<n {
19             if i > 3 && stones[i] > stones[i - 1] * 2 {
20                 return false
21             }
22             hs.insert(stones[i])
23         }
24         return canReach(hs, last, 1, 1)
25     }
26 
27     fileprivate func canReach(_ hs: Set<Int>, _ last: Int, _ pos: Int, _ jump: Int) -> Bool {
28         if pos + jump - 1 == last || pos + jump == last || pos + jump + 1 == last {
29             return true
30         }
31         if hs.contains(pos + jump + 1) {
32             if canReach(hs, last, pos + jump + 1, jump + 1) {
33                 return true
34             }
35         }
36         if hs.contains(pos + jump) {
37             if canReach(hs, last, pos + jump, jump) {
38                 return true
39             }
40         }
41         if jump > 1 && hs.contains(pos + jump - 1) {
42             if canReach(hs, last, pos + jump - 1, jump - 1) {
43                 return true
44             }
45         }
46         return false
47     }
48 }

108ms

 1 class Solution {
 2     func canCross(_ stones: [Int]) -> Bool {        
 3         guard stones.count > 1 else {
 4             return true
 5         }
 6         
 7         var memo = [Int: Int]()
 8         
 9         for i in 0..<stones.count {
10             if i > 3 && stones[i] > stones[i - 1] * 2 {
11                 return false
12             }
13             memo[stones[i]] = i
14         }
15         
16         var deadEnd = [[Bool]](repeating:[Bool](repeating:false, count:stones.count + 1), count: stones.count + 1)
17         
18 
19         
20         func jump(index:Int, preStep:Int) -> Bool {
21             if index == stones.count - 1 {
22                 return true
23             }
24             
25             if deadEnd[index][preStep] == true {
26                 return false
27             }
28             
29             if let nIndex = memo[stones[index] + preStep - 1], nIndex > index{
30                 if jump(index:nIndex ,preStep:preStep - 1) {
31                     return true
32                 } else {
33                     deadEnd[nIndex][preStep - 1] = true
34                 }
35             }
36             
37             if let nIndex = memo[stones[index] + preStep], nIndex > index {
38                 if jump(index:nIndex,preStep:preStep) {
39                     return true
40                 } else {
41                     deadEnd[nIndex][preStep] = true
42                 }
43             }
44             
45             if let nIndex = memo[stones[index] + preStep + 1], nIndex > index {
46                 if jump(index:nIndex,preStep:preStep + 1) {
47                     return true
48                 } else {
49                     deadEnd[nIndex][preStep + 1] = true
50                 }
51             }
52             
53             return false
54         }
55         
56         return jump(index:0, preStep: 0)
57     }
58 }

164ms

 1 class Solution {
 2     func canCross(_ stones: [Int]) -> Bool {
 3         var dp = [String : Bool]()
 4         var map = [Int: Int]()
 5         for i in 0..<stones.count {
 6             map[stones[i]] = i
 7         }
 8         return canCross(stones, map, from: 0, jump: 1, &dp)
 9     }
10     
11     func canCross(_ stones: [Int], _ map: [Int: Int], from i: Int, jump k: Int, _ dp: inout [String: Bool]) -> Bool {        
12         let key = "\(i)\(k)"
13         if let res = dp[key] {
14             return res
15         }
16         
17         if i == stones.count-1 {
18             dp[key] = true
19             return true
20         }
21         
22         if k <= 0 { return false }
23 
24         guard let j = map[stones[i] + k] else  {
25             dp[key] = false
26             return false
27         }
28         
29         let res = canCross(stones, map, from: j, jump: k-1, &dp) 
30             || canCross(stones, map, from: j, jump: k, &dp)
31             || canCross(stones, map, from: j, jump: k+1, &dp)
32         dp[key] = res
33         return res
34     }
35 }

256ms

 1 class Solution {
 2     func canCross(_ stones: [Int]) -> Bool {
 3         let set = Set(stones)
 4         var cache = [String: Bool]()
 5         return helper(set, 0, 0, stones.last!, &cache)
 6     }
 7     
 8     func helper(_ set: Set<Int>, _ i: Int, _ lastJump: Int, _ last: Int, _ cache: inout [String: Bool]) -> Bool {
 9         if i == last { return true }
10         if let r = cache["\(i)-\(lastJump)"] { return r }
11         let possibleJumps = Array(max(lastJump-1, 1)...max(lastJump+1, 1))
12         for j in possibleJumps {
13             if set.contains(i+j) {
14                 if helper(set, i+j , j, last, &cache) {
15                     return true
16                 }
17             }
18         }
19         cache["\(i)-\(lastJump)"] = false
20         return false
21     }
22 }

428ms

 1 class Solution {
 2     func canCross(_ stones: [Int]) -> Bool {
 3         //[stone,possibleStep]
 4         if stones.count == 2 {
 5             return stones[1] == 1
 6         }
 7         var dp = Dictionary<Int,Set<Int>>()
 8         dp[0] = Set<Int>()
 9         dp[0]!.insert(1)
10         for i in 1..<stones.count{
11             dp[stones[i]] = Set<Int>()
12         }
13         let stonesLastIndex = stones.count - 1
14         for i in 0...stonesLastIndex {
15             let stone = stones[i]
16             if let steps = dp[stone] as Set<Int>?{
17                 for step in steps {
18                     let reach = step + stone
19                     if reach == stones[stonesLastIndex]{
20                         return true
21                     }
22                     if var newStoneSet = dp[reach]{
23                         newStoneSet.insert(step)
24                         if step - 1 > 0{
25                             newStoneSet.insert(step - 1)
26                         }
27                         newStoneSet.insert(step + 1)
28                         dp[reach] = newStoneSet
29 
30                     }
31                 }
32             }
33         }
34         return false
35     }
36 }

432ms

 1 class Solution {
 2     func canCross(_ stones: [Int]) -> Bool {
 3         var m:[Int:Set<Int>] = [Int:Set<Int>]()
 4         var dp:[Int] = [Int](repeating:0,count:stones.count)
 5         var set:Set<Int> = [0]
 6         m[0] = set
 7         var k:Int = 0
 8         for i in 1..<stones.count
 9         {
10             while(dp[k] + 1 < stones[i] - stones[k])
11             {
12                 k += 1
13             }
14             for j in k..<i
15             {
16                 var t:Int = stones[i] - stones[j]
17                 if m[j] != nil && (m[j]!.contains(t - 1) || m[j]!.contains(t) || m[j]!.contains(t + 1))
18                 {
19                     if m[i] == nil
20                     {
21                         var set2:Set<Int> = [t]
22                         m[i] = set2
23                     }
24                     else
25                     {
26                         m[i]!.insert(t)
27                     }
28                     
29                     dp[i] = max(dp[i], t)
30                 }
31             }
32         }
33         return dp.last! > 0
34     }
35 }

528ms

 1 class Solution {
 2     func canCross(_ stones: [Int]) -> Bool {
 3         var result = [Int: Set<Int>]()
 4         for stone in stones {
 5             result[stone] = Set<Int>()
 6         }
 7         result[0]!.insert(0)
 8         for stone in stones {
 9             for step in result[stone]! {
10                 for newStep in step - 1...step + 1 {
11                     if newStep > 0 && result[stone + newStep] != nil {
12                         result[stone + newStep]!.insert(newStep)
13                     }
14                 }
15             }
16         }
17         return result[stones.last!]!.count > 0
18     }
19 }

536ms

 1 class Solution {
 2     func canCross(_ stones: [Int]) -> Bool {
 3         guard !stones.isEmpty else {
 4             return false
 5         }
 6 
 7         let stonesSet = Set(stones)
 8         var dict = [Int: Set<Int>]()
 9         dict[0] = [0]
10 
11         for stone in stones {
12             if let steps = dict[stone] {
13                 for step in steps {
14                     for possible in (step - 1)...(step + 1) {
15                         if possible > 0 {
16                             let nextLocation = stone + possible
17                             if stonesSet.contains(nextLocation) {
18                                 if var locationSteps = dict[nextLocation] {
19                                     locationSteps.insert(possible)
20                                     dict[nextLocation] = locationSteps
21                                 } else {
22                                     dict[nextLocation] = [possible]
23                                 }
24                             }
25                         }
26                     }
27                 }
28             }
29         }
30 
31         let last = stones.last!
32         return dict[last] != nil
33     }
34 }

564ms

 1 class Solution {
 2     func canCross(_ stones: [Int]) -> Bool {
 3         var map: [Int: Set<Int>] = [:]
 4         
 5         // stores possible steps to get to this stone
 6         for stone in stones {
 7             map[stone] = Set<Int>()
 8         }
 9         map[0]?.insert(0)
10         for stone in stones {
11             for k in map[stone]! {
12                 for step in k-1...k+1 {
13                     let newDest = stone + step
14                     if step > 0 && map.keys.contains(newDest) {
15                         map[newDest]!.insert(step)
16                     }
17                 }
18             }
19         }
20         return !map[stones.last!]!.isEmpty
21     }
22 }

704ms

 1 class Solution {
 2     func canCross(_ stones: [Int]) -> Bool {
 3         // Key is stone and array is possible steps to reach stone
 4         var map = [Int: Set<Int>]() 
 5         
 6         // fill all the stone as key to map
 7         for stone in stones {
 8             map[stone] = Set<Int>()
 9         }
10         
11         // Initialize the first first index of map with "0"
12         map[0] = [0]
13         
14         // Loop through each stone and fill the map with threee possible values        
15         for stone in stones {
16            if let stonesArray = map[stone] {
17             for possibleWay in stonesArray {
18                 
19                 for step in (possibleWay - 1 ... possibleWay + 1) {
20                     
21                     if let value = map[stone + step] {
22                         var steps = value
23                         steps.insert(step)
24                         map[stone + step] = steps
25                     }
26                 }
27              }
28         }
29         }
30         if let lastValues = map[stones[stones.count - 1]] {
31                 return lastValues.count > 0
32             }
33         return false
34     }
35 }

820ms

 1 class Solution {
 2     func canCross(_ stones: [Int]) -> Bool {
 3         var jump:[Int:Set<Int>] = [0:[1], 1:[1,2]]
 4         for i in 0..<stones.count{  
 5             if jump[stones[i]] == nil{
 6                 continue
 7             }
 8             let steps = jump[stones[i]]!
 9             for step in steps{
10                 if stones[i] + step == stones.last{
11                     return true
12                 }
13                 jump[stones[i]+step] = jump[stones[i]+step] ?? [step]
14                 if step-1 > 0{
15                     jump[stones[i]+step]?.insert(step-1)
16                 }
17                 jump[stones[i]+step]?.insert(step)
18                 jump[stones[i]+step]?.insert(step+1)
19                 
20             }
21         }
22         return false
23     }
24 }

848ms

 1 class Solution {
 2     func canCross(_ stones: [Int]) -> Bool {
 3         var map: [Int: Set<Int>] = [:]
 4         
 5         // stores possible steps to get to this stone
 6         for stone in stones {
 7             map[stone] = Set<Int>()
 8         }
 9         map[0]?.insert(0)
10         for stone in stones {
11             if stone == stones.last { return !map[stone]!.isEmpty }
12             for k in map[stone]! {
13                 for step in k-1...k+1 {
14                     let newDest = stone + step
15                     if step > 0 && map.keys.contains(newDest) {
16                         map[newDest]!.insert(step)
17                     }
18                 }
19             }
20         }
21         return false
22     }
23 }

1028ms

 1 class Solution {    
 2     var impossibleJumps: [Int: Set<Int>] = [:]
 3     func availableJumpDistance(_ lastJumpDistance: Int) -> [Int] {
 4 
 5         if lastJumpDistance <= 1 {
 6             return [1, 2]
 7         }        
 8         return [lastJumpDistance - 1, lastJumpDistance, lastJumpDistance + 1]
 9     }
10 
11     func availableStonePositions(_ lastJumpDistance: Int, _ lastStonePosition: Int) -> [Int] {
12         
13         let distances = availableJumpDistance(lastJumpDistance).map { $0 + lastStonePosition }
14         return distances
15         
16     }
17 
18     func moveFrog(stones: [Int], lastJumpDistance: Int = 1) -> [Int] {
19         guard stones.indices.contains(0) else { return [] }        
20         let currentStone = stones[0]        
21         let jumpableStones = availableStonePositions(lastJumpDistance, currentStone)        
22         for (i, stone) in stones.enumerated() {
23             if stone > jumpableStones.last ?? Int.max {
24                 break
25             }            
26             guard jumpableStones.contains(stone) else { continue }            
27             let jumpDistance = stone - currentStone            
28             if let memoryStone = impossibleJumps[stone] {
29                 if memoryStone.contains(jumpDistance) {
30                     continue
31                 }
32             }            
33             let newPath = Array(stones[i...])            
34             let newPathResult = moveFrog(stones: newPath, lastJumpDistance: jumpDistance)            
35             if newPathResult.count == 1 {
36                 return newPathResult
37             } else {
38                 if impossibleJumps[stone] == nil {
39                     impossibleJumps[stone] = [jumpDistance]
40                 } else {
41                     impossibleJumps[stone]?.insert(jumpDistance)
42                 }
43             }            
44         }
45         return stones        
46     }
47     
48     func canCross(_ stones: [Int]) -> Bool {
49         var stones = stones        
50         guard stones[1] == 1 else {
51             return false
52         }        
53         stones = Array(stones[1...])
54         // End prepare stones for crossing        
55         var lastJumpDistance = 1        
56         let result = moveFrog(stones: stones)        
57         return result.count == 1
58     }
59 }

 


1428ms

 1 class Solution {
 2     func canCross(_ stones: [Int]) -> Bool {
 3     
 4     guard stones.count >= 2 && stones[0] == 0 && stones[1] == 1 else { return false }
 5     guard checkMaxDistance(stones: stones) else { return false }
 6     var lists: [[Int:Bool]] = [[Int:Bool]](repeatElement([Int:Bool](), count: stones.count))
 7     
 8     func canCrossDP(k: Int, currentIndex: Int) -> Bool {
 9         
10         if currentIndex == stones.count - 1 { return true }
11         var index = currentIndex
12         
13         while true {
14             let distanceBetween = stones[index+1] - stones[currentIndex]
15             if k-1...k+1 ~= distanceBetween {
16                 switch distanceBetween {
17                 case k: if lists[index][k] == nil { lists[index][k] = canCrossDP(k: k, currentIndex: index+1) }
18                 case k-1: if lists[index][k-1] == nil { lists[index][k-1] = canCrossDP(k: k-1, currentIndex: index+1) }
19                 case k+1: if lists[index][k+1] == nil { lists[index][k+1] = canCrossDP(k: k+1, currentIndex: index+1) }
20                 default: break
21                 }
22             }
23             
24             if lists[index][k] ?? false || lists[index][k-1] ?? false || lists[index][k+1] ?? false { return true }
25             
26             if index + 2 < stones.count {
27                 index += 1
28             } else {
29                 return false
30             }
31         }
32     }
33     
34     return canCrossDP(k: 1, currentIndex: 1)
35 }
36 
37 func checkMaxDistance(stones: [Int]) -> Bool {
38     for i in stride(from: stones.count-1, to: 1, by: -1) {
39         if stones[i] - stones[i-1] > stones.count - 1 {
40             return false
41         }
42     }
43     return true
44  }
45 }

1500ms

 1 class Solution {
 2     func canCross(_ stones: [Int]) -> Bool {
 3         let len = stones.count
 4         var jumps = Array<(canJumpHere:Bool,kSet:Set<Int>)>.init(repeating: (false,Set<Int>()), count: len)
 5         jumps[0] = (true,Set.init(arrayLiteral: 1))
 6         
 7         for i in 0..<len {
 8             let (canJumpHere,kSet) = jumps[i]
 9             if(canJumpHere == false){ continue }
10             for j in i+1..<len {
11                 //若是兩個之間的間隔有k,那麼表明可以跳到j上
12                 let step = stones[j] - stones[i]
13                 if(kSet.contains(step)){
14                     jumps[j] = (true,jumps[j].kSet.union([step-1,step,step+1]))
15                 }
16             }
17         }
18         let (canGetHere,_) = jumps[len-1]
19         return canGetHere
20     }
21 }
相關文章
相關標籤/搜索