Leetcode刷题 9
动态规划:
第一题:爬楼梯 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相关推荐
- LeetCode刷题记录15——21. Merge Two Sorted Lists(easy)
LeetCode刷题记录15--21. Merge Two Sorted Lists(easy) 目录 LeetCode刷题记录15--21. Merge Two Sorted Lists(easy) ...
- LeetCode刷题记录14——257. Binary Tree Paths(easy)
LeetCode刷题记录14--257. Binary Tree Paths(easy) 目录 前言 题目 语言 思路 源码 后记 前言 数据结构感觉理论简单,实践起来很困难. 题目 给定一个二叉树, ...
- LeetCode刷题记录13——705. Design HashSet(easy)
LeetCode刷题记录13--705. Design HashSet(easy) 目录 LeetCode刷题记录13--705. Design HashSet(easy) 前言 题目 语言 思路 源 ...
- LeetCode刷题记录12——232. Implement Queue using Stacks(easy)
LeetCode刷题记录12--232. Implement Queue using Stacks(easy) 目录 LeetCode刷题记录12--232. Implement Queue usin ...
- LeetCode刷题记录11——290. Word Pattern(easy)
LeetCode刷题记录11--290. Word Pattern(easy) 目录 LeetCode刷题记录11--290. Word Pattern(easy) 题目 语言 思路 源码 后记 题目 ...
- 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 ...
- LeetCode刷题记录9——58. Length of Last Word(easy)
LeetCode刷题记录9--58. Length of Last Word(easy) 目录 LeetCode刷题记录9--58. Length of Last Word(easy) 题目 语言 思 ...
- LeetCode刷题记录8——605. Can Place Flowers(easy)
LeetCode刷题记录8--605. Can Place Flowers(easy) 目录 LeetCode刷题记录8--605. Can Place Flowers(easy) 题目 语言 思路 ...
- LeetCode刷题记录7——824. Goat Latin(easy)
LeetCode刷题记录7--824. Goat Latin(easy) 目录 LeetCode刷题记录7--824. Goat Latin(easy) 题目 语言 思路 后记 题目 题目需要将一个输 ...
- LeetCode刷题记录6——696. Count Binary Substrings(easy)
LeetCode刷题记录6--696. Count Binary Substrings(easy) 目录 LeetCode刷题记录6--696. Count Binary Substrings(eas ...
最新文章
- thttpd+php 不加载php.ini 问题
- Hyperopt中文文档:Cite引用
- Android WebView和JavaScript交互
- linux系统检测脚本,脚本检测linux系统资源
- C++socket编程(三):3.4 listen监听
- .net对象和比特流的转换(一)
- sar分辨率公式_购买SAR卫星三个重要参数:分辨率、极化方式、入射角
- Java在 list 中对每个元素遍历其是否在原 list 中有相同元素的方法
- Excel - 添加趋势线,显示趋势线公式 - 进行行业投融资曲线拟合
- Android Studio中修改APP图标和APP名称
- maven项目配置私服
- yum安装网络超时,尝试其他镜像
- VirtualBox主机与虚拟机互相ping通的方法
- 【工控老马】MODBUS通讯协议及编程详解
- java算法——通过身份证号获取出生的年月日
- win10读不到移动硬盘
- 百度地图——多点标记及路线
- Python之yaml与excel互相转换
- 前端例程20210510:新拟物风格(Neumorphism)设计与实现
- 美国将派大量自动昆虫机器人到火星执行任务