leetcode 64.最小路径和(minimum path sum)c语言
1.description
https://leetcode-cn.com/problems/minimum-path-sum/description/
给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明:每次只能向下或者向右移动一步。
示例:
输入: [ [1,3,1], [1,5,1], [4,2,1] ] 输出: 7 解释: 因为路径 1→3→1→1→1 的总和最小。
2.solution
回溯法加备忘录在倒数第2个case超时了
void solve(int i, int j, int dist, int gridSize, int gridColSize, int **grid, int *p, int **mem){ if(i==gridSize-1 && j==gridColSize || i==gridSize && j==gridColSize-1){ if(dist < *p){ *p = dist; } return; } if(i<gridSize && j<gridColSize){ if(dist+grid[i][j] > mem[i][j]) return; mem[i][j] = dist+grid[i][j]; solve(i+1, j, dist+grid[i][j], gridSize, gridColSize, grid, p, mem); //向下移动 solve(i, j+1, dist+grid[i][j], gridSize, gridColSize, grid, p, mem); //向右移动 } } int minPathSum(int** grid, int gridSize, int* gridColSize){ int mind = INT_MAX; // 最短路径 int *p = &mind; // 用于修改mind int **mem = (int**)malloc(gridSize*sizeof(int*)); for(int i=0; i<gridSize; ++i){ mem[i] = (int*)malloc((*gridColSize)*sizeof(int)); memset(mem[i], 127, (*gridColSize)*sizeof(int)); } solve(0, 0, 0, gridSize, *gridColSize, grid, p, mem); return mind; }
换用动态规划:
#define min(a,b) (((a) < (b)) ? (a) : (b)) int minPathSum(int** grid, int gridSize, int* gridColSize){ int **dp = (int**)malloc(gridSize*sizeof(int*)); for(int i=0; i<gridSize; ++i){ dp[i] = (int*)malloc(*gridColSize*sizeof(int)); } int sum = 0; // 初始化dp第一行 for(int i=0; i<*gridColSize; ++i){ sum += grid[0][i]; dp[0][i] = sum; } sum = 0; // 初始化dp第一列 for(int i=0; i<gridSize; ++i){ sum += grid[i][0]; dp[i][0] = sum; } for(int i=1; i<gridSize; ++i){ for(int j=1; j<*gridColSize; ++j){ dp[i][j] = grid[i][j] + min(dp[i-1][j], dp[i][j-1]); } } int res = dp[gridSize-1][*gridColSize-1]; // free for(int i=0; i<gridSize; ++i){ if(dp[i]){ free(dp[i]); } } if(dp){ free(dp); } return res; }
将二维的状态表压缩成二维的vector
#define min(a,b) (((a) < (b)) ? (a) : (b)) static inline void swap(int **p, int **q){ int *tmp = *p; *p = *q; *q = tmp; } int minPathSum(int** grid, int gridSize, int* gridColSize){ int *pre = (int*)malloc(*gridColSize*sizeof(int)); int *cur = (int*)malloc(*gridColSize*sizeof(int)); pre[0] = grid[0][0]; for(int i=1; i<*gridColSize; ++i){ pre[i] = pre[i-1] + grid[0][i]; } for(int i=1; i<gridSize; ++i){ cur[0] = pre[0] + grid[i][0]; for(int j=1; j<*gridColSize; ++j){ cur[j] = grid[i][j] + min(pre[j], cur[j-1]); } swap(&pre, &cur); } int res = pre[*gridColSize-1]; // free if(pre){ free(pre); } if(cur){ free(cur); } return res; }
进一步压缩到一维vector
#define min(a,b) (((a) < (b)) ? (a) : (b)) int minPathSum(int** grid, int gridSize, int* gridColSize){ // 将二维的状态表压缩成了一维的vector int *dp = (int*)malloc(*gridColSize*sizeof(int)); dp[0] = grid[0][0]; for(int i=1; i<*gridColSize; ++i){ dp[i] = dp[i-1] + grid[0][i]; } for(int i=1; i<gridSize; ++i){ dp[0] = dp[0] + grid[i][0]; for(int j=1; j<*gridColSize; ++j){ dp[j] = grid[i][j] + min(dp[j], dp[j-1]); } } int res = dp[*gridColSize-1]; if(dp){ free(dp); } return res; }