动态规划:
第一题:爬楼梯 leetcode 70
在爬楼梯时,每次可向上走1阶台阶或2阶台阶,问有n阶楼梯有多少种上楼的方式?

思考:用常规得到暴力搜索肯定时间通不过,故我们分析。由于每次最多爬2阶,楼梯的第i阶,只可能从楼梯的第i-1阶与第i-2阶到达,故到达第i阶有多少种爬法,只与第i-1阶、第i-2阶的爬法数量直接相关。所以第i阶的爬法数量=第i-1阶爬法数量+第i-2阶爬法数量。
1.设置地推数组dp[0…n], dp[i]代表到达第i阶,有多少种走法,初始化数组元素为0
2.设置到达第1阶台阶,有1种走法;到达第2阶台阶,有2种走法。
3.利用i循环递归从第3阶至第n阶结果:
到达第i阶的方式数量 = 到达第i-1阶的方式数量+到达第i-2阶的方式数量

#include <vector>
int climbStairs(int n){std::vector<int> dp(n+3,0);dp[1]=1;dp[2]=2;for(int i=3;i<n;i++)dp[i]=dp[i-1]+dp[i-2];return dp[n];
}

动态规划有四个步骤:
1.确认原问题与子问题;
2.确认状态:
3.确认边界状态的值:
4.确定状态转移方程:

第二题:打家劫舍 leetcode 198
在一条直线上,有n个房屋,每个房屋中有数量不等的财宝,有一个盗贼希望从房屋中盗取财宝,由于房屋中有报警器,如果同时从相邻的两个房屋中盗取财宝就会触发报警器。问在不触发报警器的前提下,最多可获取多少财宝?


思考:由于同时从相邻的两个房屋中盗取财宝就会触发报警器,故:
a.若选择第i个房间盗取财宝,就一定不能选择第i-1房间个房间盗取财宝;
b.若不选择第i个房间盗取财宝,则相当于只考虑前i-1个房间盗取财宝。


1.确认原问题与子问题:
原问题:求n个房间的最优解
子问题:求前1个房间、前2个房间、、、前n-1个房间的最优解

2.确认状态:
第i个状态即为前i个房间能够获得的最大财宝(最优解)

3.确认边界状态的值:
前1个房间的最优解,第1个房间的财宝;
前2个房间的最优解,第1、2个房间中较大财宝的。

4.确定状态转移方程:
a.选择第i个房间:第i个房间+前i-2个房间的最优解
b.不选择第i个房间:前i-1个房间的最优解
动态规划转移方程:
dp[i]=max(dp[i-1],dp[i-2]+nums[i]) ; i>=3

  int rob(vector<int>& nums){if(nums.size()==0)return 0;if(nums.size()==1)  return nums[0];vector<int> dp(nums.size(),0);dp[0]=nums[0];dp[1] = max(nums[0],nums[1]);for(int i=0i<nums.size();i++)dp[i]=max(dp[i-1],dp[i-2]+nums[i]);return dp[nums.size()-1];}

第三题:最大子段和:Leetcode 53
给定一个数组,求这个数组的连续子数组中,最大的那一段的和。
如数组[-2,1,-3,4,-1,2,1,-5,4];
连续子数组:[4,-1,2,1]为6

思路:将n个数的数组的最大子段和,转换为分别求出以第一个、第二个、、、、、第i个、、、第n个数字结尾的最大子段和,再找出这n个结果中最大的,即为结果。
动态规划算法:
第i个状态(dp[i])即为以第i个数字结尾的最大子段和(最优解)。由于以第i-1个数字结尾的最大子段和(dp[i-1])与nums[i]相邻:

 int maxSubArray(vector<int>& nums){vector<int> dp(nums.size(),0);dp[0] = nums[0];int des_max=dp[0];for(int i=1;i<nums.size();i++){dp[i] = max(dp[i-1]+nums[i],nums[i]);if(des_max<dp[i])des_max=dp[i];}return des_max;}

第四题:找零钱 leetcode 322
已知不同面值的钞票,求如何用最少数量的钞票组成某个金额,求可以使用的最少钞票数量。如果任意数量的已知面值钞票都无法组成该金额,则返回-1.
例如:
钞票面值:[1,2,5]; 金额:11=5+5+1 ; 需要3张

思路:
钞票面值:coins=[1,2,5,7,10];金额:14
dp[i],代表金额i的最优解(即最小使用张数)
数组dp[]中中存储金额1至金额14的最优解(最少使用钞票的数量)

在计算dp[i]时,dp[0]、dp[1]、dp[2]、、、dp[i-1]都是已知的:
而金额i可由:
金额i-1与coins0组合
金额i-2与coins1组合
金额i-5与coins2组合
金额i-7与coins3组合
金额i-10与coins4组合

即状态i可由状态i-1、i-2、i-5、i-7、i-10转移到


int coinChange(vector<int> & coins,int amount){vector<int> dp;for(int i=0;i<=amount;i++)dp.push_back(-1);dp[0]=coins[0];for(int i=1;i<=amount;i++){for(int j=0;j<coins.size();j++){if(i-conis[j]>0 && dp[i-coins[j]]!=-1){if(dp[i]==-1||dp[i]>dp[i-coins[j]]+1)dp[i]=dp[i-conis[j]]+1;}}}return dp[amount];}

第五题:三角形 Leetcode 120
给定一个二维数组,其保存了一个数字三角形,求从数字三角形顶端到底端各数字和最小的路径之和,每次可以向下走相邻的两个位置。

思考:从上到下或者从下导上的寻找路径的思考方式本质是一样的嘛?
假设dp[i][j]代表了数组三角形第i行、第j列的最优解,从上到下与下到上哪种方式递推更容易?(更少的考虑边界条件)


算法思路:
1、设置一个二维数组,最优值三角形dp[][],并初始化数组元素为0.dp[i][j]代表了从底向上递推时,走到三角形第i行第j列的最优解。
2、从三角形的底面向三角形上方进行动态规划:
a.动态规划边界条件:底面上的最优值即为数字三角形的最后一层。
b.利用i循环,从倒数第二层递推到第一层,对于每层的各列,进行动态规划递推:
第i行,第j列的最优解为dp[i][j],可到达(i,j)的两个位置的最优解dp[i+1][j]、dp[i+1][j+1]::
dp[i][j]=min(dp[i+1][j],dp[i+1][j+1])+triangle[i][j]
3.返回dp[0][0]

int minimumTotal(vector<vector<int>>& triangle){if(triangle.size()==0) return 0;vector<vector<int>> dp;for(int i=0;i<triangle.size();i++){dp.push_back(vector<int>());for(int j=0;j<triangle.size();j++)dp[i].push_back(0);}for(int i=0;i<dp.size();i++)dp[dp.size()-1][i]=triangle[dp.size()-1][i]; for(int i=dp.size()-2;i>=0;i--){for(int j=0;j<dp[i].size();j++){do[i]=min(dp[i+1][j],dp[i+1][j+1])+triangle[i][j];}}return dp[0][0];
}

第六题:最长上升子序列
已知一个未排序的数组,求这个数组最长上升子序列的长度。
例如:[1,3,2,3,1,4],其中最长的上升子序列长度为4。分别考虑O(n^2)与O(nlogn)两种复杂度算法
动态规划:
1.第i个状态代表前i个数字中最长上升子序列的长度,是否可找出dp[i]与dp[i-1]的关系?
2.若第i个状态代表以第i个数字为结尾的最长上升子序列的长度,是否可找出dp[i]与dp[i-1]的关系?再如何求出n个数字的最长上升子序列?
[1,3,2,3,1,4]
若第i个状态dp[i]代表以第i个元素结尾的最长上升子序列的长度:
dp[i-1]代表以第i-1个元素结尾的最长上升子序列长度,
nums[i]一定是dp[i]所对应的最长上升子序列中的最大元素(因为在末尾)

思路:设置动态规划数组dp[],第i个状态dp[i]代表以第i个元素结尾的最长上升子序列的长度:动态规划边界:dp[0]=1;
初始化最长上升子序列的长度LIS=1;
从1到n-1,循环i,计算dp[i]:
从0至i-1,循环j,若nums[i]>nums[j],说明nums[i]可放置在nums[j]的后面,组成最长上升子序列:
若dp[i]<dp[j]+1:
dp[i]=dp[j]+1
LIS为dp[0],dp[1],dp[i],dp[n-1]中最大的

int LengthOfLIS(vector<int>& nums){if(nums.size()==0) return 0;int LIS=1;vector<int> dp(nums.size(),0);dp[0]=1;for(int i=1;i<dp.size();i++){dp[i]=1;for(int j=0;j<i;j++){if(nums[i]>nums[j] && dp[i]<dp[j]+1)dp[i]=dp[j]+1;}if(LIS<dp[i])LIS=dp[i];}return LIS;
}

思路2:
设置一个栈(使用vector实现)stack,stack[i]代表长度为i+1的上升子序列最后一个元素的最小可能取值,即若要组成长度为i+2的上升子序列,需要一个大于stack[i]的元素。最终栈的大小,即为最长上升子序列的长度。

nums=[1,3,2,3,1,4]
1.设置一个栈(使用vector实现),将nums[0]push栈中。
2.从1至n-1遍历nums数组:
若nums[i]>栈顶:将nums[i]push至栈中。
否则:
从栈底遍历至栈顶,若遍历时,栈中元素大于等于nums[i],
使用nums[i]替换该元素,并跳出循环。
3.返回栈的大小

int LengthOfLIS(vector<int>& nums){if(nums.size()==0) return 0;vector<int> stack;stack.push(nums[0]);for(int i=0;i<nums.size();i++){if(nums[i]>stack.back())stack.push_back(nums[i]);else {for(int j=0;j<stack.size();j++){if(stack[j]>=nums[i])stack[j]=nums[i];}}}return stack.size();
}

第七题:最小路径和
已知一个二维数组,其中存储了非负整数,找到从左上角到右下角的一条路径,使得路径上的和最小。(移动过程中只能向下或向右)
Leetcode 64

思考:设dp[i][j]为到达位置(i,j)时的最优解(最小值):
dp[i][j]与dp[i-1][j]、dp[i][j-1]、grid[i][j]之间的关系是什么?

int minPathSum(vector<vector<int>> & grid){if(grid.size()==0)return 0;int row = grid.size();int col = grid[0].size();vector<vector<int>> dp(row,vector<int>(col,0));dp[0][0]=grid[0][0];for(int i=1;i<col;i++)dp[0][i] = dp[0][i-1]+grid[0][i];for(int i=1;i<row;i++){dp[i][0] = dp[i-1][0]+grid[i][0];for(int j=1;j<col;j++){dp[i][j]=min(dp[i-1][j],dp[i][j-1])+grid[i][j];}}return dp[row-1][col-1];
}

Leetcode刷题 9相关推荐

  1. LeetCode刷题记录15——21. Merge Two Sorted Lists(easy)

    LeetCode刷题记录15--21. Merge Two Sorted Lists(easy) 目录 LeetCode刷题记录15--21. Merge Two Sorted Lists(easy) ...

  2. LeetCode刷题记录14——257. Binary Tree Paths(easy)

    LeetCode刷题记录14--257. Binary Tree Paths(easy) 目录 前言 题目 语言 思路 源码 后记 前言 数据结构感觉理论简单,实践起来很困难. 题目 给定一个二叉树, ...

  3. LeetCode刷题记录13——705. Design HashSet(easy)

    LeetCode刷题记录13--705. Design HashSet(easy) 目录 LeetCode刷题记录13--705. Design HashSet(easy) 前言 题目 语言 思路 源 ...

  4. LeetCode刷题记录12——232. Implement Queue using Stacks(easy)

    LeetCode刷题记录12--232. Implement Queue using Stacks(easy) 目录 LeetCode刷题记录12--232. Implement Queue usin ...

  5. LeetCode刷题记录11——290. Word Pattern(easy)

    LeetCode刷题记录11--290. Word Pattern(easy) 目录 LeetCode刷题记录11--290. Word Pattern(easy) 题目 语言 思路 源码 后记 题目 ...

  6. LeetCode刷题记录10——434. Number of Segments in a String(easy)

    LeetCode刷题记录10--434. Number of Segments in a String(easy) 目录 LeetCode刷题记录9--434. Number of Segments ...

  7. LeetCode刷题记录9——58. Length of Last Word(easy)

    LeetCode刷题记录9--58. Length of Last Word(easy) 目录 LeetCode刷题记录9--58. Length of Last Word(easy) 题目 语言 思 ...

  8. LeetCode刷题记录8——605. Can Place Flowers(easy)

    LeetCode刷题记录8--605. Can Place Flowers(easy) 目录 LeetCode刷题记录8--605. Can Place Flowers(easy) 题目 语言 思路 ...

  9. LeetCode刷题记录7——824. Goat Latin(easy)

    LeetCode刷题记录7--824. Goat Latin(easy) 目录 LeetCode刷题记录7--824. Goat Latin(easy) 题目 语言 思路 后记 题目 题目需要将一个输 ...

  10. LeetCode刷题记录6——696. Count Binary Substrings(easy)

    LeetCode刷题记录6--696. Count Binary Substrings(easy) 目录 LeetCode刷题记录6--696. Count Binary Substrings(eas ...

最新文章

  1. thttpd+php 不加载php.ini 问题
  2. Hyperopt中文文档:Cite引用
  3. Android WebView和JavaScript交互
  4. linux系统检测脚本,脚本检测linux系统资源
  5. C++socket编程(三):3.4 listen监听
  6. .net对象和比特流的转换(一)
  7. sar分辨率公式_购买SAR卫星三个重要参数:分辨率、极化方式、入射角
  8. Java在 list 中对每个元素遍历其是否在原 list 中有相同元素的方法
  9. Excel - 添加趋势线,显示趋势线公式 - 进行行业投融资曲线拟合
  10. Android Studio中修改APP图标和APP名称
  11. maven项目配置私服
  12. yum安装网络超时,尝试其他镜像
  13. VirtualBox主机与虚拟机互相ping通的方法
  14. 【工控老马】MODBUS通讯协议及编程详解
  15. java算法——通过身份证号获取出生的年月日
  16. win10读不到移动硬盘
  17. 百度地图——多点标记及路线
  18. Python之yaml与excel互相转换
  19. 前端例程20210510:新拟物风格(Neumorphism)设计与实现
  20. 美国将派大量自动昆虫机器人到火星执行任务

热门文章

  1. 全面分析反应釜的防腐问题和清洗
  2. 【美团杯2020】114514 解题报告
  3. dbaas mysql,Building MySQL DBaaS on Openstack with XtraDB Cluster
  4. Kanguru推出独立于操作系统的新型加密指纹访问闪存驱动器,在竞争中脱颖而出
  5. 解决sql关键字冲突
  6. excel怎样获取单元格中特定字符前面或者后面的内容
  7. android安卓开发好网推荐
  8. Android 长时间 卡顿,安卓手机用的久了会卡顿?这几点才最有用!
  9. MYSQL的操作语句(二)
  10. 【最小割】Gym - 101982 - E - Cops And Roobers