120. Triangle

来源:互联网 发布:淘宝账号和密码共享 编辑:程序博客网 时间:2024/05/20 22:39

Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below.
For example, given the following triangle

 [     [2],    [3,4],   [6,5,7],  [4,1,8,3]]

The minimum path sum from top to bottom is 11 (i.e., 2 + 3 + 5 + 1 = 11).
Note:
Bonus point if you are able to do this using only O(n) extra space, where n is the total number of rows in the triangle.

这是一道典型的dp问题的题目,我的第一种解法很直接,思路也很简单就是自顶向下的遍历一整个三角数组,然后每一个节点都记录到这个节点的最短距离,这样时间复杂度和空间复杂度都是O(n * n)
以下是我的程序:

class Solution {public:    int minimumTotal(vector<vector<int>>& triangle) {        int n = 0;        int size = 0;        int pos = 0;        int sum = 0;        int small = 0;        std::vector<std::vector<int>> vec;        n = triangle.size();        if (n <= 0)            return sum;        std::vector<int> v;        v.push_back(triangle[0][0]);        vec.push_back(v);        for (int i = 1; i < n; i++) {            size = triangle[i].size();            std::vector<int> vec_small;            sum = vec[i - 1][0] + triangle[i][0];            vec_small.push_back(sum);            for (int j = 1; j < size - 1; j++) {                small = vec[i - 1][j - 1] <                    vec[i - 1][j] ?                     vec[i - 1][j - 1] : vec[i - 1][j];                sum = triangle[i][j] + small;                vec_small.push_back(sum);            }            sum = triangle[i][size - 1] +                     vec[i - 1][size - 2];            vec_small.push_back(sum);            vec.push_back(vec_small);        }        n = vec.size();        size = vec[n - 1].size();        small = vec[n - 1][0];        for (int i = 1; i < size; i++)            if (small > vec[n - 1][i])                small = vec[n - 1][i];               return small;    }};

但是我觉得这样的方式并不是很好,后来又改进了下,没有申请空间,而是直接在原来的三角数组上进行更改,虽然空间复杂度是O(1)但是这种方法的话不能保存数组的值,也不是很好,先看看程序:

class Solution {public:    int minimumTotal(vector<vector<int>>& triangle) {        //这种方法直接利用的就是原来的数组,每一次记录的都是        //到当前节点的最小的步数之和。这样可以节省空间,但是不能保存下原来的数据        //我使用的是top-down的方法,但是在讨论里面别人使用的是bottom-up的方法;        //我觉得bottom-up的方法很好,节约空间,实现起来也不会很难        int n = 0;        int size = 0;        int pos = 0;        int sum = 0;        int small = 0;        n = triangle.size();        if (n <= 0)            return sum;        for (int i = 1; i < n; i++) {            size = triangle[i].size();            sum = triangle[i - 1][0] + triangle[i][0];            triangle[i][0] = sum;            for (int j = 1; j < size - 1; j++) {                small = triangle[i - 1][j - 1] <                 triangle[i - 1][j] ?                     triangle[i - 1][j - 1] :                     triangle[i - 1][j];                sum = triangle[i][j] + small;                triangle[i][j] = sum;            }            sum = triangle[i][size - 1] +             triangle[i - 1][size - 2];            triangle[i][size - 1] = sum;        }        n = triangle.size();        size = triangle[n - 1].size();        small = triangle[n - 1][0];        for (int i = 1; i < size; i++)            if (small > triangle[n - 1][i])                small = triangle[n - 1][i];               return small;    }};

最后看了讨论里面别人的算法,发现还可以从底部遍历回去,这样可以做到O(n * n)的时间复杂度和O(n)的空间复杂度,以下是程序:

class Solution {public:    int minimumTotal(vector<vector<int>>& triangle) {        int n = triangle.size();        if (n == 0)            return 0;        int num = 0;        int size = triangle[n - 1].size();        int* arr = new int[size];        int small = 0;        for (int i = 0; i < size; i++)            arr[i] = triangle[n - 1][i];        for (int i = n - 2; i >= 0; i--) {            size = triangle[i].size();            for (int j = 0; j < size; j++) {                small = arr[j] < arr[j + 1] ?                     arr[j] : arr[j + 1];                arr[j] = small + triangle[i][j];            }        }        num = arr[0];        delete []arr;        return num;    }};

好啦,基本就是这样啦。

原创粉丝点击