您的位置:首页 > 其它

Triangle

2015-12-25 00:22 246 查看


package cn.edu.xidian.sselab.array;

import java.util.ArrayList;
import java.util.List;

/**
*
* @author zhiyong wang
* title: Triangle
* content:
* 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.
*
*/
public class Triangle {

//上来自己没有理解题意,以为是找到每一行的最小数据,然后求和,所以得到下面的结果,
//后来发现是错误的
public int minimumTotal(List<List<Integer>> triangle){
int length = triangle.size();
// int[] result = new int[length];
int result = 0;
for(int i=0;i<length;i++){
int width = triangle.get(i).size();
for(int j=0;j<width-1;j++){
if(triangle.get(i).get(j) < triangle.get(i).get(j+1)){
int big = triangle.get(i).get(j+1);
int small = triangle.get(i).get(j);
triangle.get(i).set(j, big);
triangle.get(i).set(j+1, small);
}
}
result += triangle.get(i).get(width-1);
}
System.out.println(result);
return result;
}

//参考答案用动态规划,时间复杂度是O(n^2)
//从第一个元素开始考虑,一直往下走,求出每行每一个点的值,最后对最后一行进行遍历,得到最小的结果
//不要需要注意第一行(只有一个顶点),每一行的第一个值与最后一个值,不用进行比较,只有一个结果
//从上到下, 下一行的结果根据上一行的路径累计和而计算。
//triangle[i][j] += min(triangle[i -1 [j -1 ],triangle[i -1 ][j ] )
public int minimumTotals(List<List<Integer>> triangle){
int length = triangle.size();
List<List<Integer>> result = new ArrayList<List<Integer>>(length);
for(int i=0;i<length;i++){
List<Integer> lines = triangle.get(i);
result.add(new ArrayList<Integer>(lines.size()));//关键所在
if(i==0){
//第一行
result.get(0).add(lines.get(0));
}else {
int size = lines.size();
for(int j=0;j<size;j++){
if(j==0){
//每一行的第一个数字
result.get(i).add(result.get(i-1).get(0) + lines.get(0));
}else if(j==size-1){
//每一行的最后一个数字
result.get(i).add(result.get(i-1).get(j-1) + lines.get(j));
}else{
if(result.get(i-1).get(j-1) + lines.get(j) > result.get(i-1).get(j) + lines.get(j)){
result.get(i).add(result.get(i-1).get(j) + lines.get(j));
}else{
result.get(i).add(result.get(i-1).get(j-1) + lines.get(j));
}
}
}
}
}
int lastLineLength = triangle.get(length-1).size();
int min = Integer.MAX_VALUE;
for(int i=0;i<lastLineLength;i++){
if(min > result.get(length-1).get(i)){
min = result.get(length-1).get(i);
}
}
return min;
}

//参考了大神为了不考虑边界问题,转为从下往上进行求解
/*键之处在于逆向思维。
* 根据题意会自然而然地想从上而下逐层寻找最优解,但是由于下层元素比上层多,
* 边界处的计算非常繁琐。但是如果自下而上,逐层计算到当前层的最优解,那么
* 到达最顶端时,就是所求最优解。
*/
public int minimumTotal2(List<List<Integer>> triangle){
int length = triangle.size();
//首先考虑特殊情况
if(triangle == null || length == 0)return 0;
if(length == 1) return triangle.get(0).get(0);
int[] below = new int[length];//用于保存下一行的最优解,
int[] cur = new int[length];//用于保存当前行的最优解

//初始化最下面一行的值
for(int i=0;i<length;i++){
below[i] = triangle.get(length-1).get(i);
}
//自底向上开始求最优解
for(int i=length-2;i>=0;i--){
List<Integer> row = triangle.get(i);
for(int j=0;j<row.size();j++){
if(below[j] < below[j+1]){
cur[j] = below[j] + row.get(j);
}else{
cur[j] = below[j+1] + row.get(j);
}
}
for(int j=0;j<row.size();j++){
below[j] = cur[j];
}
}
return cur[0];
}
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: