学习动态规划|不同路径、最小路径和、打家劫舍、打家劫舍iii
62 不同路径
动态规划,dp[i][j]表示从左上角到(i,j)的路径数量 dp[i][j] = dp[i-1][j] + dp[i][j-1]
import java. util. Arrays ;
public class $62 {
public int uniquePaths ( int m, int n) {
int [ ] [ ] dp = new int [ m] [ n] ;
for ( int i = 0 ; i < m; i++ ) {
dp[ i] [ 0 ] = 1 ;
}
for ( int i = 0 ; i < n; i++ ) {
dp[ 0 ] [ i] = 1 ;
}
for ( int i = 1 ; i < m; i++ ) {
for ( int j = 1 ; j < n; j++ ) {
dp[ i] [ j] = dp[ i- 1 ] [ j] + dp[ i] [ j- 1 ] ;
}
}
return dp[ m- 1 ] [ n- 1 ] ;
}
public int uniquePaths2 ( int m, int n) {
int [ ] dp = new int [ n] ;
Arrays . fill ( dp, 1 ) ;
for ( int i = 1 ; i < m; i++ ) {
for ( int j = 1 ; j < n; j++ ) {
dp[ j] += dp[ j- 1 ] ;
}
}
return dp[ n- 1 ] ;
}
}
import java. util. Arrays ;
public class $62 {
public int uniquePaths2 ( int m, int n) {
int [ ] dp = new int [ n] ;
Arrays . fill ( dp, 1 ) ;
for ( int i = 1 ; i < m; i++ ) {
for ( int j = 1 ; j < n; j++ ) {
dp[ j] += dp[ j- 1 ] ;
}
}
return dp[ n- 1 ] ;
}
}
64 最小路径和
动态规划,dp[i][j]表示从左上角到(i,j)的最小路径和 grid[i][j] = Math.min(grid[i-1][j], grid[i][j-1]) + grid[i][j]
public class $64 {
public int minPathSum ( int [ ] [ ] grid) {
for ( int i = 0 ; i < grid. length; i++ ) {
for ( int j = 0 ; j < grid[ i] . length; j++ ) {
if ( i== 0 && j== 0 ) continue ;
else if ( i!= 0 && j== 0 ) grid[ i] [ j] = grid[ i- 1 ] [ j] + grid[ i] [ j] ;
else if ( i== 0 && j!= 0 ) grid[ i] [ j] = grid[ i] [ j- 1 ] + grid[ i] [ j] ;
else grid[ i] [ j] = Math . min ( grid[ i- 1 ] [ j] , grid[ i] [ j- 1 ] ) + grid[ i] [ j] ;
}
}
return grid[ grid. length- 1 ] [ grid[ 0 ] . length- 1 ] ;
}
}
198 打家劫舍
动态规划,nums[i]表示前i间房屋能偷窃到的最高总金额 nums[i] = Math.max(nums[i-1], nums[i-2]+nums[i]);
public class $198 {
public int rob ( int [ ] nums) {
if ( nums == null || nums. length == 0 ) {
return 0 ;
}
if ( nums. length == 1 ) {
return nums[ 0 ] ;
}
nums[ 1 ] = Math . max ( nums[ 0 ] , nums[ 1 ] ) ;
for ( int i = 2 ; i < nums. length; i++ ) {
nums[ i] = Math . max ( nums[ i- 1 ] , nums[ i- 2 ] + nums[ i] ) ;
}
return nums[ nums. length- 1 ] ;
}
}
337 打家劫舍iii
树形动态规划 我们可以用 f(o)表示选择 o节点的情况下,o节点的子树上被选择的节点的最大权值和; g(o)表示不选择 o节点的情况下,o节点的子树上被选择的节点的最大权值和; l 和 r代表 o 的左右孩子。 当 o 被选中时:o 的左右孩子都不能被选中, 故 o 被选中情况下子树上被选中点的最大权值和为 l和 r不被选中的最大权值和 + o的值
f(o)=g(l)+g(r)+o.val
当 o不被选中时,o的左右孩子可以被选中,也可以不被选中。 对于 o的某个具体的孩子 x,它对 o 的贡献是 x被选中和不被选中情况下权值和的较大值。
g(o)=max{f(l),g(l)} + max{f(r),g(r)}
import java. util. HashMap ;
import java. util. Map ;
public class $337 {
Map < TreeNode , Integer > f = new HashMap < > ( ) ;
Map < TreeNode , Integer > g = new HashMap < > ( ) ;
public int rob ( TreeNode root) {
process ( root) ;
return Math . max ( f. getOrDefault ( root, 0 ) , g. getOrDefault ( root, 0 ) ) ;
}
private void process ( TreeNode root) {
if ( root == null ) {
return ;
}
process ( root. left) ;
process ( root. right) ;
f. put ( root, root. val + g. getOrDefault ( root. left, 0 ) + g. getOrDefault ( root. right, 0 ) ) ;
g. put ( root, Math . max ( f. getOrDefault ( root. left, 0 ) , g. getOrDefault ( root. left, 0 ) )
+ Math . max ( f. getOrDefault ( root. right, 0 ) , g. getOrDefault ( root. right, 0 ) ) ) ;
}
public int rob2 ( TreeNode root) {
int [ ] rootStatus = process2 ( root) ;
return Math . max ( rootStatus[ 0 ] , rootStatus[ 1 ] ) ;
}
private int [ ] process2 ( TreeNode root) {
if ( root == null ) {
return new int [ ] { 0 , 0 } ;
}
int [ ] l = process2 ( root. left) ;
int [ ] r = process2 ( root. right) ;
int selected = root. val + l[ 1 ] + r[ 1 ] ;
int notSelected = Math . max ( l[ 0 ] , l[ 1 ] ) + Math . max ( r[ 0 ] , r[ 1 ] ) ;
return new int [ ] { selected, notSelected} ;
}
}