玩转算法之面试第九章-动态规划

动态规划:
9-12
斐波那契数列
在这里插入图片描述
对重复计算,进行优化,进行记忆化搜索
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
假设基本的问题已经被解决,依次内推。

动态规划:将原问题拆解成若干个子问题,同时保存子问题的答案,使得每个子问题只求解一次,最终获得原问题的答案。

在这里插入图片描述

leetcode 20
在这里插入图片描述
自顶向下分析可得:
f(n)=f(n-1)+f(n-2)
在这里插入图片描述
在这里插入图片描述

将上述函数修改动态规划写法:
在这里插入图片描述
部分代码如下:

在这里插入代码片
//跳台阶 
#include<iostream>
#include<vector>
using namespace std;class Solution{private:vector<int> memo;int calcWays(int n){if(n==0 || n==1)return 1;//if(n==1)//return 1;//if(n==2)//return 2;if(memo[n]==-1)memo[n]=calcWays(n-1)+calcWays(n-2);retrun memo[n]; }public:int climbStairs(int n){memo=vector<int>(n+1,-1);return calcWays(n);}
};int main(){return 0;
}//调台阶修改成动态规划 
#include<iostream>
#include<vector>
using namespace std;class Solution{public:int climbStairs(int n){vector<int> memo(n+1,-1);memo[0]=1;memo[1]=1;for(int i=2;i<n;i++)memo[i]=memo[i-1]+memo[i-2];return memo[n];}
};

leetcode:120
在这里插入图片描述
leetcode 64
在这里插入图片描述
每一步只能左移或者下移

9-3
leetcode 343整数分割
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
最优子结构: 通过求子问题的最优解,可以获得原问题的最优解
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
部分代码如下:

在这里插入代码片
//整数分割的问题 
#include<iostream>
#include<cassert> 
#include<vector>
//记忆化搜索的关键是对访问过的值进行记录,即用memo数组对结果进行保存 using namespace std;class Solution{private:int max3(int a,int b,int c){return max(a,max(b,c));}//将n进行分割,至少分割成两部分,可以获得的最大乘积 int breakInteger(int n){if(n==1)return 1;if(memo[n]!=-1)return memo[n];int res=-1;for(int i=1; i<=n-1; i++)//i+(n-i)res=max3(res,i*(n-i),i*breakInteger(n-i));memo[n]=res;return res;	}	
public:int integerBreak(int n){assert(n>=2); memo=vector<int>(n+1,-1);return breakInteger(n);}
};int main() {return 0;
}

修改成动态规划的问题
在这里插入图片描述
部分代码如下:

//整数分割的问题 
#include<iostream>
#include<cassert> 
#include<vector>
//记忆化搜索的关键是对访问过的值进行记录,即用memo数组对结果进行保存 using namespace std;class Solution{private:int max3(int a,int b,int c){return max(a,max(b,c));}}	
public:int integerBreak(int n){assert(n>=2); //将memo[i]进行分割,至少分割成两部分,可以获得的最大乘积 vector<int> memo(n+1,-1);memo[1]=1;for(int i=1;i<n-1;i++)//求解memo[i]for(int j=1;j<=i-1;j++)//j+(i-j)memo[i]=max3(memo[i],j*(i-j),j*memo[i-j]);return memo(n);}
};int main() {return 0;
}

leetcode 279完全平方数

在这里插入图片描述
在这里插入图片描述
leetcode 91:解析方式
在这里插入图片描述
leetcode 62 不同路径
在这里插入图片描述
leetcode 63 机器人 障碍物

在这里插入图片描述

9-4
leetcode 198 打家劫舍
在这里插入图片描述
房子不相邻
价值最大
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入代码片//打家劫舍
#include<iostream>
#include<vector>using namespace std;class Solution{private://memo[i]表示抢劫nums[i...n]所能获得的最大收益vector<int> memo; //考虑抢劫nums[index...nums.size())这个范围的所有房子 int tryRob(vector<int> &nums,int index){if(index>=nums.size())return 0;if(memo[index]!=-1)return memo[index];int res=0;	for(i=index;i<nums.size();i++)res=max(res,nums[i]+tryRob(nums,i+2);	 memo[index]=res;return res;	}public:int rob(vector<int>& nums){memo=vector<int>(nums.size(),-1);return tryRob(nums,0);}}; int main(){return 0;}

修改成动态规划问题
在这里插入图片描述

在这里插入代码片
//打家劫舍动态规划 
#include<iostream>
#include<vector>using namespace std;class Solution{private:public:int rob(vector<int>& nums){int n=nums.size();if(n==0)return 0;//memo[i]表示抢劫nums[i...n-1]所能获得的最大收益vector<int>memo(n,-1);memo[n-1]=nums[n-1];for(int i=n-2;i>=0;i--)//memo[i]for(int j=i; j<n;j++)memo[i]=max(memo[i],nums[j]+(j+2<n ? memo[j+2] : 0));return memo[0];} }; int main(){return 0;} 

leetcode 213
在这里插入图片描述

leetcode 337

在这里插入图片描述
在这里插入图片描述
leetcode 309
在这里插入图片描述
设计一个自动交易算法

9-5 0-1背包问题
在这里插入图片描述
在这里插入图片描述
贪心算法?优先放入平均价值最高的物品?

在这里插入图片描述
最优解应该为22>16贪心算法
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入代码片
//0-1背包问题
#include<iostream>
#include<vector>using namespace std;class knapsack01{
private:vector<vector<int>> memo;//用[0...index]的物品,填充容积为c的背包的最大价值 int bestValue(const vector<int> &w, const vector<int> v, int index, int c){if(index<0 || c<=0)return 0;if(memo[index][c]!=-1)return memo[index][c];int res=bestValue(w,v,index-1,c);if(c>=w[index])res=max(v[index]+bestValue(w,v,index-1,c-w[index]); memo[index][c]=res;return res;}public:int knapsack01(const vector<int> &w, const vector<int> &v, int C){int n=w.size();memo=vector<vector<int>>(n,vector<int>(C+1,-1));return bestValve(w,v,n-1,c); } }; int main(){return 0;} 

如何自顶向下解决该问题
在这里插入图片描述
横轴为容量,纵轴为背包id
在这里插入图片描述
在这里插入图片描述

在这里插入代码片
//0-1背包动态规划问题 
#include<iostream>
#include<vector>using namespace std;class knapsack01{public:int knapsack01(const vector<int> &w, const vector<int> &v, int C){assert(w.size()==v.size()); int n=w.size();if(n==0 || C==0)return 0;vector<vector<int>> memo(n,vector<int>(C+1,-1));for(int j=0; j<=C; j++)memo[0][j]=(j>=w[0] ? v[0] : 0);for(int i=1; i<n; i++)for(int j=0; j<=C; j++){//0-i这些物品,背包为j memo[i][j]=memo[i-1][j];if(j>=w[i])memo[i][j]=max(memo[i][j],v[i]+memo[i-1][j-w[i]]) }return memo[n-1][C]; } }; int main(){return 0;} 

9-6
0-1背包问题的优化
在这里插入图片描述
在这里插入图片描述

在这里插入代码片
//0-1背包动态空间复杂度的优化问题 
#include<iostream>
#include<vector>using namespace std;class knapsack01{public:int knapsack01(const vector<int> &w, const vector<int> &v, int C){assert(w.size()==v.size()); int n=w.size();if(n==0 || C==0)return 0;vector<vector<int>> memo(2,vector<int>(C+1,-1));//将n改为2for(int j=0; j<=C; j++)memo[0][j]=(j>=w[0] ? v[0] : 0);for(int i=1; i<n; i++)for(int j=0; j<=C; j++){//0-i这些物品,背包为j memo[i%2][j]=memo[(i-1)%2][j];//对2取模,优化空间。从n*c的复杂度变成了2*c的复杂度 if(j>=w[i])memo[i%2][j]=max(memo[i][j],v[i]+memo[(i-1)%2][j-w[i]]) }return memo[(i-1)%2][C]; } }; int main(){return 0;} 

在这里插入图片描述
只考虑0的情况状态
在这里插入图片描述
如果现在将1纳入背包的状态,从右向左更新状态,比如5,在3的基础上加1的为16,大于6则更新为16.依次类推,更新所有状态。
在这里插入图片描述
在这里插入图片描述

在这里插入代码片
//0-1背包动态空间复杂度的继续优化问题 
#include<iostream>
#include<vector>using namespace std;class knapsack01{public:int knapsack01(const vector<int> &w, const vector<int> &v, int C){assert(w.size()==v.size()); int n=w.size();if(n==0|| C==0)return 0;vector<int> memo(C+1,-1);//将n*c改为1*c for(int j=0; j<=C; j++)memo[j]=(j>=w[0] ? v[0] : 0);for(int i=1; i<n; i++)for(int j=C; j>=w[i]; j--){//0-i这些物品,背包为j //从n*c的复杂度变成了2*c的复杂度 memo[j]=max(memo[j],v[i]+memo[j-w[i]]);}return memo[C]; } }; int main(){return 0;} 

0-1背包问题的变种

1 完全背包问题:每个物品可以无限使用
定容量,每个物品使用功能次数有最大值,对每个物品可以考虑使用二进制进行表示
2 多重背包问题:每个物品不止一个,有num[i]个
3 多维费用背包问题:要考虑物品的体积和重量两个维度?
物品间加入更多约束
物品间可以互相排斥;也可以互相依赖

9-7
leetcode 416
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

//数组分割成相等的两部分,其实也是变相的0-1背包问题,容量为sum/2
#include<iostream>
#include<vector>using  namespace std;class Solution{
private://memo[i][c]表示是否使用索引[0...i]的这些元素,是否可以完全填充一个容量为c的背包//-1 表示未计算,0表示不可以填充,1表示可以填充 vector<vector<int>> memo; //s使用nums[0...index],是否可以完全填充一个容量为sum的背包 bool tryPartition(const vector<int> &nums, int index, int sum){if(sum==0)return true;if(sum<0 || index<0)return false;if(memo[index][sum] !=-1)return memo[index][sum]==1;memo[index][sum]=(tryPartition(nums,index-1,sum) || tryPartition(nums,index-1,sum-nums[index])) ? 1 : 0 ;return memo[index][sum]==1;//等于1,则为true,反之为false }
public:bool canPartition(vector<int>& nums){int sum =0;for(int i=0;i<nums.size();i++){assert(nums[i]>0);sum+=nums[i];}if(summ%2 !=0)return false;memo=vector<vector<int>>(nums.size(),vector<int>(sum/2)); //表示memo存储了nums.size()这么多行,每一行是一个向量,并且每一行有sum/2这么多元素 tryPartition(nums,nums.size()-1,sum/2);}
}; int main(){return 0;
}

转换成动态规划问题

在这里插入图片描述

//数组分割成相等的两部分,其实也是变相的0-1背包问题,容量为sum/2
//转换成动态规划问题 
#include<iostream>
#include<vector>
#include<cassert> using  namespace std;class Solution{public:bool canPartition(vector<int>& nums){int sum =0;for(int i=0;i<nums.size();i++){assert(nums[i]>0);sum+=nums[i];}if(summ%2 !=0)return false;int n=nums.size();int C=sum/2;vector<boo> memo(C+1,false);for(int i=-; i<=C;i++){memo[i]=(nums[0]==i);for(int i=1; i<n;i++)for(int j=C,j>=nums[i];j--)memo[j]=memo[j] || memo[j-nums[i]];return memo[C];}}
}; int main(){return 0;
}

练习: leetcode 322 硬币换现
在这里插入图片描述
leetcode 377 数组凑数
在这里插入图片描述
leetcode 474 01串
在这里插入图片描述
在这里插入图片描述
leetcode 139 字符串连接
在这里插入图片描述

leetcode 494 给定整数sum
在这里插入图片描述
9-8 9
leetcode 300最长上升子序列的长度
在这里插入图片描述
边界情况:当两个元素是否相等的情况,这种情况他是否算在里面
在这里插入图片描述
在这里插入图片描述
初始化为1
在这里插入图片描述
根据状态方程更新各个长度值
在这里插入图片描述
最后扫描一组的最大值
在这里插入图片描述

在这里插入图片描述
//最长上升子序列 //o(n^2)
#include
#include

using namespace std;

class Solution{

public:
int lengthOfLIS(vector& nums){

	if(nums.size()==0)return 0;//memo[i] 表示nums[i]为结尾的最长上升子序列的长度 vector<int> memo(nums.size(), 1);for(int i=1; i<nums.size(),i++)for(int j=0; j<i; j++)if(nums[j]<nums[i])memo[i]=max(memo[i],1+memo[j]);int res=1;for(int i=0; i<nums.size(); i++)res=max(res,memo[i]);return res; } }; int main(){return 0;}

思考
在这里插入图片描述leetcode: 376 升降轮流序列

在这里插入图片描述
最长公共子序列
longgest common sequence
在这里插入图片描述
图论中最短路径
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/480073.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

领域应用 | 从本体论开始说起——运营商关系图谱的构建及应用

本文转载自公众号&#xff1a;中国联通大数据。联通大数据技术专家闫龙将从“本体论”说起&#xff0c;为大家介绍联通大数据关系图谱的构建与应用。一&#xff0e;本体论万维网之父Tim Berners-Lee教授在1998年将语义网络&#xff08;Semantic web&#xff09;带入人类的视线。…

史上最强多线程面试44题和答案:线程锁+线程池+线程同步等

最全BAT必考题答案系列 最全MySQL面试60题和答案 史上最全Spring面试71题与答案 史上最全Redis面试49题&#xff08;含答案&#xff09;:哨兵复制事务集群持久化等 分布式缓存RedisMemcached经典面试题和答案 最全Java锁详解&#xff1a;独享锁/共享锁公平锁/非公平锁乐观锁…

部门直推!百度大搜索招聘NLP、搜索方向算法工程师!

星标/置顶小屋&#xff0c;带你解锁最萌最前沿的NLP、搜索与推荐技术工作职责负责百度搜索排序相关性&#xff08;Relevance&#xff09;策略。 职位要求-了解主流机器学习算法。 -优秀的分析问题和解决问题的能力&#xff0c;对解决具有挑战性问题充满激情。 -C/C语言编程&…

POJ 1276 ATM凑钱(动态规划)(未解答)

文章目录1. 题目1.1 题目链接1.2 题目大意1.3 解题思路2. 代码2.1 Accepted代码1. 题目 1.1 题目链接 http://poj.org/problem?id1276 1.2 题目大意 需要凑的钱最多100000&#xff0c;面额最多10种&#xff0c;每种张数最多1000&#xff0c;面额最大不超过1000 1.3 解题思…

论文浅尝 | 为基于知识库的问答构建形式查询生成

论文笔记整理&#xff1a;刘晓臻&#xff0c;东南大学计算机科学与工程学院本科生。Citation: H.Zafar, G. Napolitano, and J. Lehmann. Formal query generation for questionanswering overknowledge bases. ESWC, 2018.https://link.springer.com/content/pdf/10.1007%2F97…

Java多线程系列(十一):ReentrantReadWriteLock的实现原理与锁获取详解

我们继续Java多线程与并发系列之旅&#xff0c;之前我们分享了Synchronized 和 ReentrantLock 都是独占锁&#xff0c;即在同一时刻只有一个线程获取到锁。 然而在有些业务场景中&#xff0c;我们大多在读取数据&#xff0c;很少写入数据&#xff0c;这种情况下&#xff0c;如…

这篇顶会paper,讲述了疫情期间憋疯的你和我

星标/置顶小屋&#xff0c;带你解锁最萌最前沿的NLP、搜索与推荐技术编 | 小轶2020年净忙着见证历史了。年初疫情爆发后&#xff0c;大家的生活模式也因为疫情发生了巨变。经历了史上最长假期&#xff0c;躺尸太久&#xff0c;到后来满脑子只想开学/复工。今年KDD会议上有一篇很…

论文浅尝 | Knowledge Vault: 全网规模的知识概率融合方法

论文笔记整理&#xff1a;吴桐桐&#xff0c;东南大学博士生&#xff0c;研究方向为自然语言处理。链接&#xff1a;https://www.cs.ubc.ca/~murphyk/Papers/kv-kdd14.pdf基于机器学习&#xff0c;Knowledge Vault不仅能够从多个来源&#xff08;文本&#xff0c;表格数据&…

java程序员的必用的9款开发工具

今天推荐java程序员开发利器&#xff0c;包含如如下&#xff1a; 开发环境&#xff1a; Eclipse IntelliJ IDEA IntelliJ在业界被公认为最好的java开发工具之一&#xff0c;尤其在智能代码助手、代码自动提示、重构、J2EE支持、各类版本工具&#xff08;git、svn等&#xff…

动态规划应用--搜索引擎拼写纠错

文章目录1. 字符串相似度1.1 莱文斯坦距离1.2 最长公共子串长度2. 计算编辑距离2.1 莱文斯坦距离2.2 最长公共子串长度3. 搜索引擎拼写纠错4. 练习题在 Trie树那节讲过&#xff0c;利用Trie可以进行关键词提示&#xff0c;节省输入时间。在搜索框中你不小心打错了字&#xff0c…

玩转算法之面试第十章-贪心算法

leetcode 455 分配饼干 尝试将最大的饼干给最贪心的朋友 如果满足&#xff0c;则1 如果不满足&#xff0c;则将最大的饼干给次贪心的朋友&#xff0c;一次类推 试图让最多的小朋友开心 在这里插入代码片 #include<iostream> #include<vector>using namespace …

论文浅尝 | 基于知识库的自然语言理解 04#

本文转载自公众号&#xff1a;知识工场。罗康琦&#xff0c;上海交通大学计算机系2019届博士&#xff0c;研究方向为自然语义理解和知识图谱。2012年获得华中科技大学软件工程学士学位&#xff0c;现就职于京东数据科学实验室&#xff08;Data Science Lab&#xff09;。他曾在…

BERT跨模态之后:占领了视觉常识推理任务榜单TOP 2!

星标/置顶小屋&#xff0c;带你解锁最萌最前沿的NLP、搜索与推荐技术文 | 小鹿鹿lulu编 | YY前言由于 BERT-like 模型在 NLP 领域上的成功&#xff0c;研究者们开始尝试将其应用到更为复杂的 多模态 任务上。要求模型除文本数据以外&#xff0c;还要接收其他模态的数据&#xf…

常见的算法面试问题以及代码实现

1 时间复杂度分析 一个简单的时间测试代码如下&#xff1a; #include<iostream> #include<cmath> #include<ctime>using namespace std;int main(){for(int x1;x<9;x){int npow(10,x);clock_t startTimeclock();int sum0;for(int i0;i<n;i)sumi;clock…

阿里P8架构师谈:高并发与多线程的关系、区别、高并发的技术方案

什么是高并发&#xff1f; 高并发&#xff08;High Concurrency&#xff09;是一种系统运行过程中遇到的一种“短时间内遇到大量操作请求”的情况&#xff0c;主要发生在web系统集中大量访问收到大量请求&#xff08;例如&#xff1a;12306的抢票情况&#xff1b;天猫双十一活动…

LeetCode 1. 两数之和(哈希)

文章目录1. 题目2. 解题1. 暴力解法2. 哈希法3. python3解答1. 题目 题目链接&#xff1a;https://leetcode-cn.com/problems/two-sum/ 给定一个整数数组 nums 和一个目标值 target&#xff0c;请你在该数组中找出和为目标值的那 两个 整数&#xff0c;并返回他们的数组下标。…

论文浅尝 | TuckER:基于张量分解的知识图谱补全

笔记整理&#xff1a;孙泽群&#xff0c;南京大学计算机科学与技术系&#xff0c;博士研究生。论文链接&#xff1a;https://arxiv.org/abs/1901.09590背景知识图谱是图结构的数据库&#xff0c;以三元组(es, r, eo)的形式存储事实&#xff0c;其中es和eo分别表示主语和宾语实体…

阿里Java P系列技术要求(P5-P7)

阿里p系列薪资&#xff08;最新数据比这个高1倍左右&#xff09; 阿里P5&#xff08;高级研发工程师&#xff09; 工作要求&#xff1a; 能独立完成日常工作&#xff0c;并能够对一些方案提出自己的建议。 基本考核就是能上手独立完成工作&#xff0c;熟练掌握。 技能要求…

如何配置一台深度学习工作站?

星标/置顶小屋&#xff0c;带你解锁最萌最前沿的NLP、搜索与推荐技术这篇文章主要介绍的是家用的深度学习工作站&#xff0c;典型的配置有两种&#xff0c;分别是一个 GPU 的机器和四个 GPU的机器。如果需要更多的 GPU 可以考虑配置两台四个 GPU 的机器。如果希望一台机器同时具…

LeetCode 2. 两数相加(单链表反转)

题目链接&#xff1a;https://leetcode-cn.com/problems/add-two-numbers/ 给出两个 非空 的链表用来表示两个非负的整数。其中&#xff0c;它们各自的位数是按照 逆序 的方式存储的&#xff0c;并且它们的每个节点只能存储 一位 数字。 如果&#xff0c;我们将这两个数相加起…