开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第18天,点击查看活动详情
恰好移动 k 步到达某一位置的方法数目
给你两个 正 整数 startPos 和 endPos 。最初,你站在 无限 数轴上位置 startPos 处。在一步移动中,你可以向左或者向右移动一个位置。
给你一个正整数 k ,返回从 startPos 出发、恰好 移动 k 步并到达 endPos 的 不同 方法数目。由于答案可能会很大,返回对 109 + 7 取余 的结果。
如果所执行移动的顺序不完全相同,则认为两种方法不同。
注意:数轴包含负整数。
示例1:
输入:startPos = 1, endPos = 2, k = 3
输出:3
解释:存在 3 种从 1 到 2 且恰好移动 3 步的方法:
- 1 -> 2 -> 3 -> 2.
- 1 -> 2 -> 1 -> 2.
- 1 -> 0 -> 1 -> 2.
可以证明不存在其他方法,所以返回 3 。
示例2:
输入: startPos = 2, endPos = 5, k = 10
输出: 0
解释: 不存在从 2 到 5 且恰好移动 10 步的方法。
提示:
1 <= startPos, endPos, k <= 1000
解题思路:
只记录上一步走到了哪些坐标还不够,还得记录有多少次走到了上一步的坐标
所以用一个map来记录 key做坐标, value做个数
我的答案:
var numberOfWays = function(startPos, endPos, k) {
const diff = Math.abs(startPos - endPos);
let rest = k - diff;
if(rest < 0 || (rest&1)) return 0;
const mod = (10**9) + 7
const dp = Array.from({length: k + 1}, ()=> new Map()); //dp: [map]
dp[0].set(startPos, 1);
for(let i=1; i<=k; i++) {
const preMap = dp[i-1]; //上一步的map, key是坐标, value是个数;
for(const [pos, count] of preMap) { //遍历上一步的坐标和个数
const prePos = pos - 1; //下一步向前走的坐标
const nextPos = pos + 1; //下一步向后走的坐标
const curMap = dp[i];
if(!curMap.has(prePos)) curMap.set(prePos, 0);
if(!curMap.has(nextPos)) curMap.set(nextPos, 0);
//累加
curMap.set(prePos, (curMap.get(prePos) + count) % mod)
curMap.set(nextPos, (curMap.get(nextPos) + count) % mod)
}
}
return dp[k].get(endPos); //返回第k步时 在endPos坐标上的个数
};
最后
如果有更好的解法或者思路, 欢迎在评论区和我交流~ ღ( ´・ᴗ・` )