为什么要刷leetcode?
要开始刷力扣啦,主要是希望自己通过刷题对于之前学习算法以及数据结构有一个更深入的理解,同时也为复试可能的机试做准备。自从上次蓝桥杯以后,已经有整整一年没有刷了,回忆起来之前在java俱乐部刷题的日子,zz老师其实真的是一个超级负责超级棒的老师~
但是当时刷题,对于java的语法并不是十分熟悉,每次一遇到不会的题目就直接看解析,然后i,就是背代码。。。对于背后的算法没有真正弄清楚,同样的题目,放了几天又不会了,然后现在对于基本的分治算法、动态规划都已经完全没有印象了,后面上最喜欢的王磊老师的算法课也没有认真听讲,最后考试都是硬背代码o(╯□╰)o
怎么刷?
我觉得leetcode刷题还是要严格保证质量,每天写一两道题目就好了,但必须要弄懂背后的算法以及设计原理,每道题目会有算法讲解,但不能没有思路的时候马上就看答案,还是得要认真去思考,做好笔记!
了解到一般学校的复试都是要求C语言或是C++,但是真的好喜欢Java(只记得java了),所以这段时间准备算法比赛就先用Java刷题叭。
什么是动态规划
递归和动态规划都是将原问题拆成多个子问题然后求解,他们之间最本质的区别是,动态规划保存了子问题的解
64.最小路径和
由于路径的方向只能是向下或向右,因此网格的第一行的每个元素只能从左上角元素开始向右移动到达,网格的第一列的每个元素只能从左上角元素开始向下移动到达,此时的路径是唯一的,因此每个元素对应的最小路径和即为对应的路径上的数字总和。
对于不在第一行和第一列的元素,可以从其上方相邻元素向下移动一步到达,或者从其左方相邻元素向右移动一步到达,元素对应的最小路径和等于其上方相邻元素与其左方相邻元素两者对应的最小路径和中的最小值加上当前元素的值。由于每个元素对应的最小路径和与其相邻元素对应的最小路径和有关,因此可以使用动态规划求解。
创建二维数组 \textit{dp}dp,与原始网格的大小相同,\textit{dp}[i][j]dp[i][j] 表示从左上角出发到 (i,j)(i,j) 位置的最小路径和。显然,\textit{dp}[0][0]=\textit{grid}[0][0]dp[0][0]=grid[0][0]。对于 \textit{dp}dp 中的其余元素,通过以下状态转移方程计算元素值。
当 i>0i>0 且 j=0j=0 时,\textit{dp}[i][0]=\textit{dp}[i-1][0]+\textit{grid}[i][0]dp[i][0]=dp[i−1][0]+grid[i][0]。
当 i=0i=0 且 j>0j>0 时,\textit{dp}[0][j]=\textit{dp}[0][j-1]+\textit{grid}[0][j]dp[0][j]=dp[0][j−1]+grid[0][j]。
当 i>0i>0 且 j>0j>0 时,\textit{dp}[i][j]=\min(\textit{dp}[i-1][j],\textit{dp}[i][j-1])+\textit{grid}[i][j]dp[i][j]=min(dp[i−1][j],dp[i][j−1])+grid[i][j]。
最后得到 \textit{dp}[m-1][n-1]dp[m−1][n−1] 的值即为从网格左上角到网格右下角的最小路径和。
class Solution {
public int minPathSum(int[][] grid) {
if(grid==null||grid.length==0||grid[0].length==0)
return 0;
int rows=grid.length;
int columns=grid[0].length;
int dp[][]=new int[rows][columns];
dp[0][0]=grid[0][0];
for(int i=1;i<rows;i++){
dp[i][0] = dp[i - 1][0] + grid[i][0];
}
for (int j = 1; j < columns; j++) {
dp[0][j] = dp[0][j - 1] + grid[0][j];
}
for (int i = 1; i < rows; i++) {
for (int j = 1; j < columns; j++) {
dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j];
}
}
return dp[rows - 1][columns - 1];
}
}
明天有一个校级CCCC团队程序设计天梯赛的预选赛,这段时间摆烂没有好好准备,对于java的基本语法API都忘得差不多了啊啊啊啊,希望能通过叭,通过了就好好准备国赛\0◇0/