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

来源:互联网 发布:csm欢网实时数据 首页 编辑:程序博客网 时间:2024/05/16 10:34

题目要求:
给定数组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 65535class 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,路漫漫其修远兮

0 0