您的位置:首页 > 理论基础 > 数据结构算法

数据结构和算法经典100题-第21题

2015-12-16 10:56 525 查看
题目要求:

给定数组arr,arr[i] == k代表可以从位置i向右跳1~k个距离,比如,arr[2] == 3,代表从位置2可以跳到位置3、位置4或位置5,如果从位置0出发,返回最少跳几次能跳到arr最后的位置上?

解析:

思路:可以考虑从两个角度解决这个问题,关键在于选择参考标准,第一种可以把这个问题归结为到达每个固定坐标至少需要多少步。显然不符合贪心条件,想到用动态规划打表解决。OK这是一种思路。

从另一个角度观察此问题,此问题可以总结为跳跃X步最远能到哪的问题,只要满足X步最远能到的坐标大于等于所求的坐标就可以。下面根据这两个思路分别给出代码和复杂度分析。

思路一:动态规划:

头文件

#ifndef _ALG_15TH_H_
#define _ALG_15TH_H_

#include <vector>

#define MAX_STEPS 65535

class SkipArray {
public:
SkipArray();
~SkipArray();
int minStep(std::vector<int> &inputArray);
int minStep(std::vector<int> &inputArray, std::vector<int> &path);
};

#endif


#include <stdio.h>
#include <iostream>
#include <vector>
#ifdef _METHOLD_1_
#include "15.h"

using namespace std;

SkipArray::SkipArray() {}

SkipArray::~SkipArray() {}

int SkipArray::minStep(std::vector<int> &inputArray) {
int size = inputArray.size();
if (0 == size || 65535 < size) {
cout<<"minStep --inputArray is illegal."<<endl;
return 0;
}

vector<int> steps;
for (int i = 0; i < size; ++i)
{
steps.push_back(MAX_STEPS);
}

// O(N^2)
steps[0] = 0;
for (int i = 0; i < (int)size; ++i) {
for (int j = 0; j <= inputArray[i]; ++j) {
if (steps[i+j] > steps[i] + 1) {
steps[i+j] = steps[i] + 1;
}
}
}

for (int i = 0; i < size; i++) {
cout<<"steps["<<i<<"] = "<<steps[i]<<endl;
}

return steps[9];
}

int main(void) {
int iarray[] = {3,3,2,5,1,1,1,1,1,1};
size_t count = sizeof(iarray)/sizeof(int);
vector<int> ivec(iarray,iarray+count);
SkipArray skipArray;
count = skipArray.minStep(ivec);
//    count = minStep(ivec);
// cout<<"Min steps = "<<count<<endl;
return 0;
}


可以看到打印结果是3步,是正确的,但时间复杂度是O(N^2),空间复杂度是O(N)

接下来看第二种思路。

int minStep(std::vector<int> &array) {
if (array.empty()) {
cout<<"minStep array is empty."<<endl;
return 0;
}

int current = 0;
int jump = 0;
int next = 0;
int tmp = 0;
int size = (int)array.size();
//next = array[0];
cout<<"array size = "<<size<<endl;
// 时间复杂度O(N),空间复杂度O(1)
for (int i = 0; i < size; ++i) {
if (next >= size - 1) {
return current+1;
}

if (jump >= i) {
int tmp = array[i] + i;
next = (next < tmp) ? tmp : next;
} else {
current++;
jump = next;
}
}

return current;
}
int main(void) {
int iarray[] = {3,3,2,5,1,1,1,1,1,1};
size_t count = sizeof(iarray)/sizeof(int);
vector<int> ivec(iarray,iarray+count);
//  SkipArray skipArray;
//  count = skipArray.minStep(ivec);
count = minStep(ivec);
cout<<"Min steps = "<<count<<endl;
return 0;
}


第一种方法时间复杂度是O(N^2),空间复杂度是O(N);

可以看到第二种方法的时间复杂度是O(N),空间复杂度是O(1)。

所以第二种方法更优。

OKay,路漫漫其修远兮
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息