zoukankan      html  css  js  c++  java
  • leetcode—triangle

    1.题目描述

    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).

    2.解法分析

    此题最简单的想法就是一个深度搜索,将所有可能的路径全部找出来,比较它们的和,于是有了如下的代码:

    class Solution {
    public:
        int minimumTotal(vector<vector<int> > &triangle) {
            // Start typing your C/C++ solution below
            // DO NOT write int main() function
            //by areslipan@163.com
            int minTotal= 0;
            
            for(int i = 0;i<triangle.size();++i)
            {
                minTotal+=triangle[i][0];
            }
            triangleHeight = triangle.size();
            int depth = 1;
            int curSum = 0;
            
            minnum(triangle,minTotal,1,0,curSum);
            
            return minTotal;
            
        }
       
        void minnum(vector<vector<int>> &triangle,int & minTotal,int depth,int loc,int &curSum)
        {
        
            curSum+=triangle[depth-1][loc];
            if(depth == triangleHeight)
            {
                minTotal = minTotal<curSum?minTotal:curSum;return;
            }
            
            minnum(triangle,minTotal,depth+1,loc,curSum);
            curSum -= triangle[depth][loc];
            minnum(triangle,minTotal,depth+1,loc+1,curSum);
            curSum -= triangle[depth][loc+1];
        }
         private:
        int triangleHeight;
        
    };

    在小数据集上运行良好,但是大数据集上就不行了,归根结底,深度遍历一方面有重复计算,一方面有递归消耗,再加上是个O(N2)的算法,必定会很慢,不过深度遍历的算法很直观,可以作为进一步分析的基础。既然知道深度搜索不行,那么该怎么办呢,我们发现,其实这个三角是有很强的最优子结构的,分析如下:

    如果最短路径通过第i层(最上一层为0层,第一个元素标号为0)的第j个元素,那么必然有最短路径通过第i层的第j-1或者第j个元素,这种二选一的情形是由题意限定的,对于每一层的首尾需特殊处理,如果最短路径通过i层的首尾元素,说明最优路径在上一层的节点已经确定。于是,若已知截止于第i-1层的各个元素的最短路径和SUMi-1(SUM为长度为i的数组),那么截止于第i层的最短路径和SUMi的每个元素可以按照如下公式计算:

    • SUMi[j] = min(SUMi-1[j-1],SUMi-1[j]) +triangle[i][j]      若 j>0且j<i
    • SUMi[0] = SUMi-1[0]+triangle[0][0];
    • SUMi[i]  =SUMi-1[i-1] +triangle[i][i];

    于是有了以下的代码:

    class Solution {
    public:
        int minimumTotal(vector<vector<int> > &triangle) {
            // Start typing your C/C++ solution below
            // DO NOT write int main() function
            //areslipan@163.com
            
            int triangleHeight = triangle.size();
            if(triangleHeight==0)return 0;
            
            //申请一个长度为n的辅助空间,作为动态规划的备忘表
            //备忘表被循环利用,第i个循环中只有前i个元素有意义,存放的是遍历到第i层的最佳路径对应的最小值
            vector<int> mmtTable;
            mmtTable.assign(triangleHeight,0);
            mmtTable[0]= triangle[0][0];
           
            int tmp = 0;
            for(int i = 1;i<triangleHeight;++i)
            {
                //特殊处理每一层的第一个元素,因为第一个元素的上一个节点一定是上一层的第一个元素
                int cur = mmtTable[0];
                mmtTable[0] = cur + triangle[i][0];
                
                //第i层的中间节点j可能上一层节点是第i-1层的j-1和j个节点
                for(int j=1;j<i;++j)
                {
                    tmp = mmtTable[j];
                    mmtTable[j] = min(cur,mmtTable[j])+triangle[i][j];
                    cur = tmp;
                }
                
                //特殊处理每一层的最后一个元素,因为最后一个元素的上一个节点一定是上一层的最后一个元素
                mmtTable[i] = cur+triangle[i][i];
            }
            
            vector<int>::iterator iter;
            int minTotal = mmtTable[0];
            for(iter = mmtTable.begin();iter!=mmtTable.end();++iter)
            {
                if((*iter)<minTotal)minTotal = *iter;
            }
            
            return minTotal;
            
            
        }
    };
  • 相关阅读:
    CSS实现的几款不错的菜单栏
    成长经历之新年感触
    Jquery实现的几款漂亮的时间轴
    一些常用的前端基础操作
    数据图表插件echarts(二)
    数据图表插件Echarts(一)
    jQuery的属性
    jQuery的61种选择器
    JavaScript基础知识总结(四)
    JavaScript基础知识总结(三)
  • 原文地址:https://www.cnblogs.com/obama/p/3251196.html
Copyright © 2011-2022 走看看