方法一:
线段树,从后往前dp,当前dp值为从当前点能跳到的后面最长的距离内的最小dp值+1,线段树可以O(log(n))的时间内从后面找到最小的dp值
struct segTree{
int l,r;
int v;
segTree* left,*right;
segTree(int val):v(val),left(NULL),right(NULL){}
};
void build(segTree*& root,int l,int r)
{
if(l==r)
{
root=new segTree(l);
root->l=l;
root->r=l;
return;
}
root=new segTree(l);
root->l=l;
root->r=r;
int mid=(l+r)>>1;
build(root->left,l,mid);
build(root->right,mid+1,r);
}
void insert(segTree*& root,int dp[],int ind,int val)
{
if(root->l==root->r&&root->l==ind)
{
return;
}
if(dp[root->v]>val)
root->v=ind;
int mid=(root->l+root->r)>>1;
if(ind<=mid)
insert(root->left,dp,ind,val);
else
insert(root->right,dp,ind,val);
}
int search(segTree* &root,int dp[],int l,int r)
{
if(root->l>r||root->r<l)
return -1;
if(root->l==l&&root->r==r)
return root->v;
int mid=(root->l+root->r)>>1;
if(r<=mid)
return search(root->left,dp,l,r);
else if(l>=mid+1)
return search(root->right,dp,l,r);
int lind=search(root->left,dp,l,mid);
int rind=search(root->right,dp,mid+1,r);
if(dp[lind]>dp[rind])
return rind;
return lind;
}
class Solution {
public:
int jump(vector<int>& nums) {
int n=nums.size();
if(n<=1)
return 0;
int dp[n];
for(int i=0;i<n;i++)
dp[i]=n;
dp[n-1]=0;
segTree* root;
build(root,0,n-1);
insert(root,dp,n-1,0);
for(int i=n-2;i>=0;i--)
{
if(nums[i]==0)
continue;
int ind=search(root,dp,i+1,min(i+nums[i],n-1));
dp[i]=dp[ind]+1;
insert(root,dp,i,dp[i]);
}
return dp[0];
}
};
方法二:贪心,维持一个当前步能到达的最大值,多加一步能到达的最大值
class Solution {
public:
int jump(vector<int>& nums) {
int n=nums.size();
if(n<=1)
return 0;
int curRch=0;
int curMax=0;
int ret=0;
for(int i=0;i<n;i++)
{
if(curRch<i)
{
ret++;
curRch=curMax;
}
curMax=max(curMax,nums[i]+i);
}
return ret;
}
};