【算法】Number of Ways to Stay in the Same Place After Some Steps 有多少种移动一定步数后留在原位置的路径

题目

ou have a pointer at index 0 in an array of size arrLen. At each step, you can move 1 position to the left, 1 position to the right in the array or stay in the same place (The pointer should not be placed outside the array at any time).

Given two integers steps and arrLen, return the number of ways such that your pointer still at index 0 after exactly steps steps.

Since the answer may be too large, return it modulo 10^9 + 7.

Example 1:

Input: steps = 3, arrLen = 2
Output: 4
Explanation: There are 4 differents ways to stay at index 0 after 3 steps.
Right, Left, Stay
Stay, Right, Left
Right, Stay, Left
Stay, Stay, Stay
Example 2:

Input: steps = 2, arrLen = 4
Output: 2
Explanation: There are 2 differents ways to stay at index 0 after 2 steps
Right, Left
Stay, Stay
Example 3:

Input: steps = 4, arrLen = 2
Output: 8

Constraints:

1 <= steps <= 500
1 <= arrLen <= 10^6

有一个长度为 arrLen 的数组,其实位置为 0 ,每次可以向右一步、向左一步、留在原地,经过 steps 次操作后,仍处于位置 0 ,一共有多少种路径可以满足要求。
由于结果可能非常大,可以用 10^9 + 7 取模。
约束条件:
1 <= steps <= 500
1 <= arrLen <= 10^6

解题思路

  1. 如要第 n 步在位置 0, 则第 n-1 步应该位于位置 0 或者位置 1
  2. 若要第 n-1 步在位置 0 ,则第 n-2 步应该位于位置 0 或者位置 1
  3. 若要第 n-1 步在位置 1 ,则第 n-2 步应该位于位置 0 、位置 1 或者位置 2
  4. 。。。

这是动态规划问题,正向解析就是

  1. 一步到达位置 0 和位置 1 的路径数量为 1,arr1[0]=1,arr1[1]=1,
  2. 两步可到达的位置最远为位置 2 或者数组长度 arrLen<2 ,并且可以由一步到达的路径数量加的,arr2[0]=arr1[0]+arr1[1],arr2[1]=arr1[0]+arr1[1]+arr1[2],arr2[2]=arr1[1]+arr1[2]+arr1[3],arr2[arrLen-1]=arr1[arrLen-2]+ar1r[arrLen-1]
  3. 三步可到达的位置最远为位置3 或者数组长度 arrLen<3 ,并且可以由两步到达的路径数量加的,arr3[0]=arr2[0]+arr2[1],arr3[1]=arr2[0]+arr2[1]+arr2[2],...,arr3[arrLen-1]=arr2[arrLen-2]+arr2[arrLen-1]

代码实现

func numWays(_ steps: Int, _ arrLen: Int) -> Int {
        //若步数或者长度为1时,则只有一种路径
        if arrLen <= 1 || steps <= 1{
            return 1
        }
        //设置模
        let mod = 1000000007
        //初始化一步到达的路径数量数组,可达最远位置1,长度为1+1=2,但由于计算二步到达路径数量数组时,会用到一步到达位置2的路径数量,所以需要额外加一个元素,即长度为2+1=3
        var arr = [1, 1, 0]
        //循环从二步到steps步
        for i in 2 ... steps {
            //可到达的最远位置为步数与数组长度的较小值
            let max = min(arrLen-1, i)
            //初始化临时i步到达的路径数量数组,长度为(max+1)+1=max+2
            var temp = [Int](repeating: 0, count: max+2)
            //循环i步可到达位置 0 ~ max 的路径数量数组
            for j in 0 ... max{
                //先获取 i-1 步到达位置 j 的路径数量
                var ans = arr[j]
                switch j {
                //若位置 j 为 0 则加位置 1 的路径数量
                case 0:
                    ans = (ans + arr[1]) % mod
                //若位置 j 为 max 则加位置 max-1 的路径数量
                case max:
                    ans = (ans + arr[max-1]) % mod
                //若位置 j 不为 0 或者 max 则加位置 j-1 和 j+1 的路径数量
                default:
                    ans = (arr[j-1] + ans + arr[j+1]) % mod
                }
                //将 i 步到达位置 j 的路径数量赋值到临时数组的对应位置
                temp[j]=ans
            }
            //将临时i步到达的路径数量数组赋值与 arr 以便求取 i+1 步到达路径数组时用
            arr = temp
        }
        //遍历结束后,arr 即为 steps 步可到达路径数量数组,arr[0] 即为 steps 步到达位置 0 的路径数量
        return arr[0]
    }

代码地址:https://github.com/sinianshou/EGSwiftLearning

推荐阅读更多精彩内容