第一种思路是:
dp(i):到位置i所需要的最少步数
dp(i)一定是递增的,所以从j=A[i]开始(从最远的位置开始),更新数组直到dp(j+i) <= dp(i) + 1为止
如果去掉,会TLE
int jump(int A[], int n) {
int* dp = new int[n];//dp[i]到i所需的最小步数
memset(dp, 0x3f, sizeof(int) * n);
dp[0] = 0;
for (int i = 0; i < n; i++)
{
for (int j = A[i]; j > 0 ; j--)
{
if (j + i >= n - 1) return min(dp[n-1], dp[i] + 1);
if (dp[j + i] <= dp[i] + 1) break;
dp[j + i] = dp[i] + 1;
}
}
return dp[n - 1];
}
另外一种思路是
maxPos(i):走i步最远的位置
int jump(int A[], int n) {
vector<int> maxPos;
maxPos.push_back(0);
maxPos.push_back(A[0]);
if (n <= 1) return 0;
if (A[0] >= n - 1) return 1;
for(int index = 2; index < n; index++)
{
int max = 0;
for (int k = maxPos[index - 2] + 1; k <= maxPos[index - 1]; k++)
{
if (max < A[k] + k)
{
max = A[k] + k;
if (max >= n - 1)
return index;
}
}
maxPos.push_back(max);
}
return n;
}
由于只用到了maxPos的index-1和index-2位置,可以进一步优化空间为O(1)的,用两个变量记录当前最大的和上一个最大的位置即可
下面是leetcode讨论里的解法,原理是一样的
int jump(int A[], int n) {
int ret = 0;
int last = 0;
int curr = 0;
for (int i = 0; i < n; ++i) {
if (i > last) {
last = curr;
++ret;
}
curr = max(curr, i+A[i]);
}
return ret;
}