题目链接:https://leetcode-cn.com/problems/zui-xiao-tiao-yue-ci-shu/
题意
有一排n个点,每个点有一个转移长度jump[i],表示从i点可转移到 i + j u m p [ i ] i+jump[i] i+jump[i]点,或者可以转移到i前面的所有点,问从0号点转移到n或n后面的点需要至少多少次转移
题解
直接bfs维护0到当前点的最小距离即可,往前可以直接搜索,往后的搜索有单调性,一旦1到x被回退更新过就不可能再次更新,所以维护一个last表示1到last-1都被更新过,这样就可以
O
(
n
)
O(n)
O(n)求解问题
也可以使用dp方法解决,从后往前dp
dp一样有单调性,每次考虑往后转移的时候,只要转移到一个x满足dp[x]<dp[i]+1,那么x以后的都会更小(dp[k]<=dp[x]+1<=dp[i]+1),所以只需要转移到x以前就行
code
bfs
const int N = 1000001;
int vis[N];
int n;
void init()
{
for (int i = 0; i < n; i++)
vis[i] = 0;
}
int bfs(vector<int> &nxt)
{
queue<pair<int, int>> qu;
qu.push(make_pair(0, 1));
vis[0] = 1;
int last = 1;
while (!qu.empty())
{
pair<int, int> p = qu.front();
qu.pop();
int u = p.first;
int d = p.second;
if (u + nxt[u] >= n)
return d + 1;
if (!vis[u + nxt[u]])
{
qu.push(make_pair(u + nxt[u], d + 1));
vis[u + nxt[u]] = 1;
}
for (int i = last; i < u; i++)
{
if (!vis[i])
{
vis[i] = 1;
qu.push(make_pair(i, d + 1));
}
}
last = u;
}
return -1;
}
class Solution
{
public:
int minJump(vector<int> &jump)
{
n = jump.size();
init();
return bfs(jump);
}
};
dp
class Solution {
public:
int minJump(vector<int>& jump) {
int n = jump.size();
if(jump[0]>=n)return 1;
int dp[n];
dp[n-1]=1;
for(int i=n-2;i>=0;--i){
if(i+jump[i]>=n)dp[i]=1;
else{
dp[i]=dp[i+jump[i]]+1;
}
for(int j=i+1;j<n&&dp[j]>=dp[i]+1;++j){
dp[j]=dp[i]+1;
}
}
return dp[0];
}
};