三角形最小路径和(个人解题思路记录)

题目:

给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。

相邻的结点 在这里指的是 下标 与 上一层结点下标 相同或者等于 上一层结点下标 + 1 的两个结点。

     [

          [2],

         [3,4],

        [6,5,7],

       [4,1,8,3]

     ]

示例,返回11,路径为2-3-5-1,不要求返回路径,辅助空间不限(越小越好)

解:

说一下我自己的解题过程,最开始想到的是递归,递归也可以解出来,但是无用的计算太多了,所以最终使用动态规划进行计算。

递归:

/// 寻找三角形最短路径
    /// - Parameters:
    ///   - triangle: 二维数组
    ///   - i: 当前起始i,最开始应该传0
    ///   - j: 当前起始j,最开始应该传0
    ///   - currentSum: 当前位置之前的最小值
    /// - Returns: 最小值
    func findChild(_ triangle: [[Int]], _ i : Int, _ j : Int, _ currentSum : Int) -> Int {
        let sums = currentSum + triangle[i][j];
        let n = triangle.count;
        if i == n - 1 {
            //叶子
            return sums;
        }
        let sum1 = findChild(triangle, i + 1, j, sums);
        let sum2 = findChild(triangle, i + 1, j + 1, sums);
        return sum1 < sum2 ? sum1 : sum2;
    }

递归方法的复杂度会跟二维数组的复杂度 呈现指数增长。所以不可能用该方法。

动态规划:

func minimumTotal(_ triangle: [[Int]]) -> Int {
        let n = triangle.count;
        if n == 1 {
            return triangle[0][0];
        }
        if n == 0 {
            return 0;
        }
        //数组也可以换成字典(hashMap)[Int: Int]()
        var arr = [Int]();
        for _ in (0...(n - 1)) {
            arr.append(0);
        }
        arr[0] = triangle[0][0];
        for i in (1...(n - 1)) {
            for j in (0...i).reversed() {
                /*
                 这里倒序的原因是,不覆盖j。可能说这比较绕,可以自己找个简单的二维数组推一遍
                 假设不倒序的话,会发生什么,怎么避免?处理后和倒序比有什么变化?
                 不倒序的话:会在计算j位置的时候覆盖j,再计算加1后的(j + 1)位置时,使用的j位置的值不正确
                 如何避免:可以再建一个n的数组(或者使用n*n的二维数组),来记录i,j位置值。
                 处理后和倒序相比:处理后,使用的空间增加n(或n*(n-1)),相对来说增加了辅助空间
                 */
                if j == 0 {
                    arr[j] = arr[j] + triangle[i][j];
                } else if j == i {
                    arr[j] = arr[j - 1] + triangle[i][j];
                } else {
                    arr[j] = (arr[j] < arr[j - 1] ? arr[j] : arr[j - 1]) + triangle[i][j];
                }
            }
        }
        var num : Int = arr[0];
        for i in (1...(n - 1)) {
            let curNum = arr[i];
            if curNum < num {
                num = curNum;
            }
        }
        return num;
    }

个人认为,动态规划最重要的是寻找规律,找到规律后,即可实现。

简单介绍一下,上面的。

可以建立一个n*n的二维数组,利用i,j位置记录到达i,j位置的最短路径。

上面的代码,利用一个n的数组,来记录到达最底层i位置的最短路径。

测试代码:

func testMinimumTotal() {
        let aa = [
             [2],
            [3,4],
           [6,5,7],
          [4,1,8,3]
        ];
        
        var a = findChild(aa, 0, 0, 0);
        var a1 = minimumTotal(aa);
        
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值