Leetcode 第120题 三角形最小路径和
给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。
相邻的结点 在这里指的是 下标 与 上一层结点下标 相同或者等于 上一层结点下标 + 1 的两个结点。
例如,给定三角形:
[ [2], [3,4], [6,5,7], [4,1,8,3] ]
自顶向下的最小路径和为 11
(即,2 + 3 + 5 + 1 = 11)。
说明:
如果你可以只使用 O(n) 的额外空间(n 为三角形的总行数)来解决这个问题,那么你的算法会很加分。
解题思路
首先 题目说了自上而下,然后只能往相邻的元素走, 相邻 就是 索引 一样 或者 索引 + 1, 所以 它的next 就是它下一层 的 索引和当前一样 或者索引 +1。
理论上 要找到 最小的路径和,我们要对所有可能要找的路径 进行计算然后取最小的。
动态规划
这题可以用动态规划的思想,一上来如果没有方向的话,我们 可以找一个小的子问题去解决它,也许写着写着 就有灵感了。那么 我们先尝试着看看 怎么找下一个相邻节点。
pub fn minimum_total(triangle: Vec<Vec<i32>>) -> i32 { let floor = triangle.len() -1; // triangle.len() -1 最后一层没有下一个节点 不需要找 for i in 0..triangle.len() -1{ for j in 0..triangle[i].len(){ if j + 1 < triangle[i + 1].len() { print!(" | {} next {} {}",triangle[i][j],triangle[i + 1][j],triangle[i + 1][j +1]); }else{ print!("{} next {} ",triangle[i][j],triangle[i + 1][j]); } } println!(); } 1 } fn main() { let angle:Vec<Vec<i32>> = vec![ vec![2], vec![3,4], vec![6,5,7], vec![4,1,8,3]]; minimum_total(angle); }
我们找到了,每一个数的下一个相邻节点,除了最后一层 没有下一个相邻节点,有了 相邻节点 我们就可以计算 当前 节点 到相邻节点的和了,有了这个基础 我们 只需要 把 每一步 和上一步的 值 相加 就可以得出答案了。
我的思路是 定义一个lastsummary 用来记录 上一层的信息。

如上图,每一个节点 是上一个节点之和, 由于只能往右,所以我们知道每一个节点的上一个节点 必然是 自身的index 或者 index-1 ,那么 我们一开始 使用一个 lastsummary 里面包含一个 0。
那么 第一层 2 + 0 =2 lastsummary =[2]
第二层 3 + 2 = 5 、4 + 2 = 6 lastsummary = [5,6]
我们是通过 当前index 和当前 index -1 索引 的 上一层的 lastsummary,如果 得出2个值,如第三层 10 和 11 ,它们其实所处的位置都是一样的 所以 2者我们取其中最小值,就可以了。
use std::cmp::{max, min}; pub fn minimum_total(triangle: Vec<Vec<i32>>) -> i32 { if triangle.len() == 0{ return 0;} let mut sum = vec![0]; for i in 0..triangle.len(){ let mut floor = vec![]; for j in 0..triangle[i].len(){ if j < 1 { floor.push(sum[j] + triangle[i][j]); }else if( j == triangle[i].len() -1 ){ floor.push(sum[j -1] + triangle[i][j]); } else { floor.push(min(sum[j-1] + triangle[i][j],sum[j] + triangle[i][j])); } } sum = floor; } *sum.iter().min().unwrap() } fn main() { let angle:Vec<Vec<i32>> = vec![ vec![-1], vec![2,3], vec![1,-1,-3]]; println!("{}",minimum_total(angle)); }
算法复杂度:O(n)
空间复杂度:O(n)
