第一题:经典爬楼梯问题
假设你正在爬楼梯,需要n步你才能到达顶部。但每次你只能爬一步或者两步,你能有多少种不同的方法爬到楼顶部?
样例 1:
输入: n= 3
输出: 3
样例解释:
1) 1, 1, 1
2) 1, 2
3) 2, 1
共3种
样例 2:
输入: n = 1
输出: 1
解释:
只有一种方案
public class Solution {
/**
* @param n: An integer
* @return: An integer
*/
public int climbStairs(int n) {
int[] dp = new int[1000];
dp[1] = 1;
dp[2] = 2;
for(int i=3;i<=n;i++){
dp[i] = dp[i-1]+dp[i-2];
}
return dp[n];
}
}
第二题: 最小路径和
给定一个只含非负整数的m*n网格,找到一条从左上角到右下角的可以使数字和最小的路径。
你在同一时间只能向下或者向右移动一步
样例 1:
输入: [[1,3,1],[1,5,1],[4,2,1]]
输出: 7
样例解释:
路线为: 1 -> 3 -> 1 -> 1 -> 1。
样例 2:
输入: [[1,3,2]]
输出: 6
解释:
路线是: 1 -> 3 -> 2
补充知识:如何求二维数组行和列的值?
int [][] arr = new int[3][4];
System.out.println(arr.length); //打印出二维数组的行数:3
System.out.println(arr[0].length); //打印出二维数组的列数:4
arr.length这个经常被我弄错,arr.length打印出的是二维数组的行数,而不是12!
public class Solution {
/**
* @param grid: a list of lists of integers
* @return: An integer, minimizes the sum of all numbers along its path
*/
public int minPathSum(int[][] grid) {
if(grid==null||grid[0]==null){
return -1;
}
int m = grid.length;
int n = grid[0].length;
int[][] dp = new int[m][n];
dp[0][0] = grid[0][0];
for(int i=1;i<n;i++){
dp[0][i] = dp[0][i-1] + grid[0][i];
}
for(int i=1;i<m;i++){
dp[i][0] = dp[i-1][0] + grid[i][0];
}
for(int i=1;i<m;i++){
for(int j=1;j<n;j++){
dp[i][j] = Math.min(dp[i-1][j],dp[i][j-1])+grid[i][j];
}
}
return dp[m-1][n-1];
}
}
优化解法(空间):
public class Solution {
/**
* @param grid: a list of lists of integers
* @return: An integer, minimizes the sum of all numbers along its path
*/
public int minPathSum(int[][] grid) {
if(grid==null||grid[0]==null){
return -1;
}
int length = grid[0].length;
int[] dp = new int[length];
dp[0] = grid[0][0];
for(int i=1;i<length;i++){
dp[i] = dp[i-1]+grid[0][i];
}
for(int i=1;i<grid.length;i++){
dp[0] = dp[0] + grid[i][0];
for(int j=1;j<length;j++){
dp[j] = Math.min(dp[j-1],dp[j])+grid[i][j];
}
}
return dp[length-1];
}
}
第三题:不同的路径
有一个机器人的位于一个 m × n 个网格左上角。
机器人每一时刻只能向下或者向右移动一步。机器人试图达到网格的右下角。
问有多少条不同的路径?
n和m均不超过100
public class Solution {
/**
* @param m: positive integer (1 <= m <= 100)
* @param n: positive integer (1 <= n <= 100)
* @return: An integer
*/
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 class Solution {
/**
* @param m: positive integer (1 <= m <= 100)
* @param n: positive integer (1 <= n <= 100)
* @return: An integer
*/
public int uniquePaths(int m, int n) {
int[] dp = new int[n];
for(int i=0;i<n;i++){
dp[i] = 1;
}
for(int j=1;j<m;j++){
for(int i = 1;i<n;i++){
dp[i] = dp[i-1]+dp[i];
}
}
return dp[n-1];
}
}
第四题:不同的路径II
"不同的路径" 的跟进问题:
现在考虑网格中有障碍物,那样将会有多少条不同的路径?
网格中的障碍和空位置分别用 1 和 0 来表示。
m 和 n 均不超过100
public class Solution {
/**
* @param obstacleGrid: A list of lists of integers
* @return: An integer
*/
public int uniquePathsWithObstacles(int[][] obstacleGrid) {
if(obstacleGrid==null||obstacleGrid[0]==null){
return -1;
}
int m = obstacleGrid.length;
int n = obstacleGrid[0].length;
int[][] dp = new int[m][n];
if(obstacleGrid[0][0]==0){
dp[0][0]=1;
}else{
return 0;
}
for(int i=1;i<m;i++){
if(obstacleGrid[i][0]==1){
dp[i][0] = 0;
}
else{
dp[i][0] = dp[i-1][0];
}
}
for(int i=1;i<n;i++){
if(obstacleGrid[0][i]==1){
dp[0][i] = 0;
}
else{
dp[0][i] = dp[0][i-1];
}
}
for(int i=1;i<m;i++){
for(int j=1;j<n;j++){
if(obstacleGrid[i][j]==1){
dp[i][j]=0;
}
else{
dp[i][j] = dp[i-1][j] + dp[i][j-1];
}
}
}
return dp[m-1][n-1];
}
}
优化解法(节省空间):
public class Solution {
/**
* @param obstacleGrid: A list of lists of integers
* @return: An integer
*/
public int uniquePathsWithObstacles(int[][] obstacleGrid) {
if(obstacleGrid==null||obstacleGrid[0]==null){
return -1;
}
int n = obstacleGrid[0].length;
int[] dp = new int[n];
if(obstacleGrid[0][0]==0){
dp[0] = 1;
}else{
return 0;
}
for(int i=1;i<n;i++){
if(obstacleGrid[0][i]==1){
dp[i] = 0;
}else{
dp[i] = dp[i-1];
}
}
for(int i=1;i<obstacleGrid.length;i++){
if(obstacleGrid[i][0]==1){
dp[0] = 0;
}
for(int j=1;j<n;j++){
if(obstacleGrid[i][j]==1){
dp[j] = 0;
}else{
dp[j] = dp[j-1]+dp[j];
}
}
}
return dp[n-1];
}
}
第五题:数字三角形
给定一个数字三角形,找到从顶部到底部的最小路径和。每一步可以移动到下面一行的相邻数字上。
如果你只用额外空间复杂度O(n)的条件下完成可以获得加分,其中n是数字三角形的总行数。
样例
example 1
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).
example 2
Given the following triangle:
[
[2],
[3,2],
[6,5,7],
[4,4,8,1]
]
The minimum path sum from top to bottom is 12 (i.e., 2 + 2 + 7 + 1 = 12).
public class Solution {
/**
* @param triangle: a list of lists of integers
* @return: An integer, minimum path sum
*/
public int minimumTotal(int[][] triangle) {
int m = triangle.length;
int n = triangle[m-1].length;
for(int i=m-2;i>=0;i--,n--){
for(int j=0;j<=n-2;j++){
triangle[i][j] += Math.min(triangle[i+1][j],triangle[i+1][j+1]);
}
}
return triangle[0][0];
}
}
哈哈,我打算从今天开始每天刷5到LintCode上的算法题,在此立下flag!当然啦,作为一个算法上的小菜鸟,我肯定是先从最简单的刷起啦,这样就能一点一点的进步,也有助于我能坚持下去!今天的5道题圆满完成!
今天的算法题是动态规划方面的习题,都是比较简单和基础的,而且还有助于举一反三,找到动态规划的一种节省空间的做法后,我发现这一小类题似乎都可以这样做!
等着明天我再来刷题哟~~~~
最后附上今天拍的美图一张~~~~