三角形最小路径和

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

例如,给定三角形:

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

自顶向下的最小路径和为 11(即,3 + 1 = 11)。

说明:

如果你可以只使用 O(n) 的额外空间(n 为三角形的总行数)来解决这个问题,那么你的算法会很加分。

解题思路:典型的动态规划问题,把三角形看作是二维数组的左下半部分,那么问题就变成求解转移矩阵最下面一排的最小值,具体来说,左下列只需要用本数值+上方数值,对角线只需要用本数值+左上方数值,中间的部分则是用 本数值+上方数值、本数值+左上方数值中的最小值,依次递推。

    public static int minimumTotal(List<List<Integer>> triangle) {
    	/* 三角形:
    	 * 2 0 0 0
    	 * 3 4 0 0
    	 * 6 5 7 0
    	 * 4 1 8 3
    	 * 可以生成的最小路径是:
    	 * 2  0  0  0
    	 * 5  6  0  0
    	 * 11 10 13 0
    	 * 15 11 18 16
    	 * 也就是说,每一个点的最小路径,是当前点的值加 [正上] [左上] 的值 的最小值
    	 * */
    	
    	/*
    	 * -1 0
    	 * -2 -3
    	 * */
    	int result = 0;
    	int length = triangle.size();
    	//如果数组为空,直接返回0
        if(length==0){
            return 0;
        }
    	//定义二维数组存放三角形
    	int [][]a = new int[length][length];
    	for(int i=0;i<length;i++){
        	for(int j=0;j<=i;j++){//对二维数组的左下侧赋值
        		a[i][j] = triangle.get(i).get(j);
        	}
    	}
    	//输出初始数组
//    	for(int i=0;i<length;i++){
//        	for(int j=0;j<length;j++){
//        		System.out.printf(a[i][j]+" ");
//        	}
//        	System.out.println();
//    	}
//    	System.out.println();
    	//对二维数组进行转移操作
    	//首先左下是依次累加的
    	for(int i=1;i<length;i++){
    		a[i][0] = a[i][0] + a[i-1][0];
    	}
    	//其次对角线也是依次累加的
    	for(int i=1;i<length;i++){
        		a[i][i] = a[i][i] + a[i-1][i-1];
//        		System.out.println(a[i][i]+"");
    	}
    	//然后中间的一小部分(左列和对角线之间的部分),从左上角开始往右下角推,每个数字是其本身与 [上方]/[左上]相加结果中的最小值
    	for(int i=1;i<length;i++){
        	for(int j=1;j<i;j++){        		
        		a[i][j] = Math.min( (a[i-1][j-1]+a[i][j]) , (a[i-1][j]+a[i][j]) );
        	}
    	}
    	//输出转移后的数组
//    	for(int i=0;i<length;i++){
//        	for(int j=0;j<length;j++){
//        		System.out.printf(a[i][j]+" ");
//        	}
//        	System.out.println("");
//    	}
    	//结果是最后一行的最小值
    	result = a[length-1][0];
    	for(int j=0;j<length;j++){
    		if(a[length-1][j] < result){
    			result = a[length-1][j];
    		}
    	}
		return result;      
    }


	public static void main(String[] args) {
		List<Integer> a1 = new ArrayList<Integer>();
		List<Integer> a2 = new ArrayList<Integer>();
		List<Integer> a3 = new ArrayList<Integer>();
		List<Integer> a4 = new ArrayList<Integer>();

		a1.add(-1);
		a2.add(-2);a2.add(-3);

//		a1.add(2);
//		a2.add(3);a2.add(4);
//		a3.add(6);a3.add(5);a3.add(7);
//		a4.add(4);a4.add(1);a4.add(8);a4.add(3);

		List<List<Integer>>a = new ArrayList<List<Integer>>();;
		a.add(a1);
		a.add(a2);
//		a.add(a3);
//		a.add(a4);

		System.out.println(minimumTotal(a));
	}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值