• [Swift]LeetCode403. 青蛙过河 | Frog Jump


    原文地址:https://www.cnblogs.com/strengthen/p/10311244.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.

    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.

    Note:

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

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

    [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 个单元格,并且在每一个单元格内都有可能放有一石子(也有可能没有)。 青蛙可以跳上石头,但是不可以跳入水中。

    给定石子的位置列表(用单元格序号升序表示), 请判定青蛙能否成功过河(即能否在最后一步跳至最后一个石子上)。 开始时, 青蛙默认已站在第一个石子上,并可以假定它第一步只能跳跃一个单位(即只能从单元格1跳至单元格2)。

    如果青蛙上一步跳跃了 个单位,那么它接下来的跳跃距离只能选择为 k - 1或 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个石子之间的间距太大,没有可选的方案供青蛙跳跃过去。

    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 }
  • 相关阅读:
    Thinkphp5+PHPExcel实现批量上传表格数据
    使用ECharts画K线图
    ThinkPHP5+Layui实现图片上传加预览
    SVN使用教程总结
    JS内置对象方法
    头像上传【实用php】
    Sublime Text 3 快捷键总结
    javascript--基础 三元表达式
    javascript---运算符、表达式、递增、比较运算符、逻辑运算符
    导入dmp的sql语句
  • 原文地址:https://www.cnblogs.com/strengthen/p/10311244.html
Copyright © 2020-2023  润新知