在线编程(三)
来源:互联网 发布:mac安装windows系统 编辑:程序博客网 时间:2024/05/02 20:37
1.斐波那契数列
思路1:直接递归调用,时间复杂度
int Fibonacci(int n){if(n==1 || n==2)return n;return Fibonacci(n-1) + Fibonacci(n-2);}
思路2:动态规划,将前n次的结果保存,时间复杂度
int Fibonacci(int n){if(n==1 || n==2)return n;int now=1;int pre=1;for(int i=2;i<n;i++){now=now+pre; pre=now-pre;}return now;}
思路3:
可以写成矩阵的形式:
由上式可以得到:
//注:懒得换编译器,还是用的vs2008,一些C++11的特性不支持,矩阵赋值比较繁琐,可以考虑重写个矩阵的类,重载=vector<vector<int>> multMatrix(vector<vector<int>> a,vector<vector<int>> b)//矩阵乘法{ int temp=0; vector<int> tmp; vector<vector<int>> res; for(int i=0;i<a.size();i++)//m { for(int j=0;j<b[0].size();j++)//n { for(int k=0;k<a[0].size();k++)//n { temp+=a[i][k]*b[k][j]; } tmp.push_back(temp); temp=0; } res.push_back(tmp); tmp.clear(); } return res;}vector<vector<int>> powerN(vector<vector<int>> a,int n)//矩阵的n次方,这里直接写了2*2的单位阵{ vector<vector<int>> tmp; vector<vector<int>> sum; vector<int> temp; temp.push_back(a[0][0]); temp.push_back(a[0][1]); tmp.push_back(temp); temp.clear(); temp.push_back(a[1][0]); temp.push_back(a[1][1]); tmp.push_back(temp); temp.clear(); temp.push_back(1); temp.push_back(0); sum.push_back(temp); temp.clear(); temp.push_back(0); temp.push_back(1); sum.push_back(temp); int m=1; while(n!=0) { if((n&1)!=0) { sum=multMatrix(sum,tmp); } tmp=multMatrix(tmp,tmp); n=n>>1; } return sum;}int Fibonacci(int n){ if(n==1 || n==2) return 1; vector<vector<int>> a; vector<vector<int>> b; vector<int> temp; temp.push_back(1); temp.push_back(1); a.push_back(temp); temp.clear(); temp.push_back(1); temp.push_back(0); a.push_back(temp); b= powerN(a,n-2); return b[0][0]+b[1][0]; }
类似的问题还有:台阶问题(初始值不同),牛的繁殖问题
2.矩阵的最小路径和:给定一个矩阵,从矩阵的左上角开始,每次向下或向右,最后到达右下角的位置,路径上的所有数字加起来就是路径和。
思路:dp[i][j]存储从左上角到达m[i][j]的最小路径,第一行和第一列的数即为该列/该列到该位置的和。从m[0][0]到m[i][j]的路径必经过m[i][j-1]或m[i-1][j],d[i][j]=min{d[i-1][j],d[i][j-1]}+m[i][j]
int minPath(vector<vector<int>> m){ vector<vector<int>> dp; dp.resize(m.size()); for(int i=0;i<m.size();i++) dp[i].resize(m[0].size()); dp[0][0]=m[0][0]; for(int j=1;j<m[0].size();j++) dp[0][j]=dp[0][j-1]+m[0][j]; for(int i=1;i<m.size();i++) dp[i][0]=dp[i-1][0]+m[i][0]; for(int i=1;i<m.size();i++) for(int j=1;j<m.size();j++) { dp[i][j]=min(dp[i-1][j],dp[i][j-1])+m[i][j]; } return dp[m.size()-1][m[0].size()-1];}
思路2:减少空间复杂度的一种算法,如果列数大于行数,则从左往右更新数组,如果行数大于列数,则从上往下更新
int minPath2(vector<vector<int>> m){ vector<int> dp; int more=max(m.size(),m[0].size()); int less=min(m.size(),m[0].size()); bool rowmore=more==m.size();//如果rowmore==1 说明行数大于列数 dp.resize(less); dp[0]=m[0][0]; for(int i=1;i<less;i++) dp[i]=dp[i-1]+(rowmore?m[0][i]:m[i][0]); for(int i=1;i<more;i++) { dp[0]=dp[0]+(rowmore?m[i][0]:m[0][i]); for(int j=1;j<less;j++) dp[j]=min(dp[j],dp[j-1])+(rowmore?m[i][j]:m[j][i]); } return dp[less-1];}
3.换钱的最少货币:定义一个数组,表示货币的面值,每种货币不限数目,再给定一个值aim表示要换的钱,给出一个表示aim的最少货币数。
变:换钱的方法数
#include <iostream>#include <vector>using namespace std;/**************************暴力递归**************/ int process1(vector<int> arr,int index,int aim) { int res=0; if (index==arr.size()) res=aim==0?1:0; else { for(int i=0;arr[index]*i<=aim;i++) res+=process1(arr,index+1,aim-arr[index]*i); } return res; }int coins1(vector<int> arr,int aim){ if(arr.size()==0 || aim==0) return 0; return process1(arr,0,aim);}/*********************************************************/ /****************************记忆搜索*********************/ //时间复杂度O(N*aim^2) int process2(vector<int> arr,int index,int aim,vector<vector<int>> &map) { int res=0; int mapvalue; if (index==arr.size()) res=aim==0?1:0; else { for(int i=0;arr[index]*i<=aim;i++) { mapvalue=map[index+1][aim-arr[index]*i]; if(mapvalue!=0) { res+=mapvalue==-1?0:mapvalue; } else { res+=process2(arr,index+1,aim-arr[index]*i,map); } } } map[index][aim]=res==0?-1:res; return res; } int coins2(vector<int> arr,int aim) { vector<vector <int> > map(arr.size()+1 ,vector<int>(aim+1)); if(arr.size()==0 || aim==0) return 0; return process2(arr,0,aim,map); }/*********************************************************/ /****************************动态规划*********************/ //时间复杂度O(N*aim^2) int coins3(vector<int> arr,int aim) { int n=arr.size(); vector<vector<int>> dp(n,vector<int>(aim+1)); for(int i=0;i<n;i++) { dp[i][0]=1; } for(int j=0;j<=aim;j++) { if(j%arr[0]==0) { dp[0][j]=1; } else { dp[0][j]=INT_MAX; } } int res=0; for(int i=1;i<n;i++) for(int j=1;j<=aim;j++) { for(int k=0;j-arr[i]*k >=0;k++) { if(dp[i-1][j-arr[i]*k]!=INT_MAX) res+=dp[i-1][j-arr[i]*k]; } dp[i][j]=res; res=0; } return dp[n-1][aim]; }/*********************************************************/ /****************************动态规划2*********************///时间复杂度O(N*aim) int coins4(vector<int> arr,int aim) { int n=arr.size(); vector<vector<int>> dp(n,vector<int>(aim+1)); for(int i=0;i<n;i++) { dp[i][0]=1; } for(int j=0;j<=aim;j++) { if(j%arr[0]==0) { dp[0][j]=1; } else { dp[0][j]=INT_MAX; } } int res=0; for(int i=1;i<n;i++) for(int j=1;j<=aim;j++) { res=dp[i-1][j]; if(j-arr[i]>=0 && dp[i][j-arr[i]]!=INT_MAX) if(res!=INT_MAX) res+=dp[i][j-arr[i]]; else res=dp[i][j-arr[i]]; dp[i][j]=res; res=0; } return dp[n-1][aim]; }int main(){ vector<int> arr; arr.push_back(5); arr.push_back(10); arr.push_back(25); arr.push_back(1); int aim=15;// int res1=coins1(arr,aim);// cout<<res1<<endl;// int res2=coins2(arr,aim);// cout<<res2<<endl;// int res3=coins3(arr,aim);// cout<<res3<<endl; int res4=coins4(arr,aim); cout<<res4<<endl; return 0;}
阅读全文
0 0
- 在线编程(三)
- 剑指offer在线编程(三)
- 赛码网—在线编程(三)翻转数组
- 在线编程(一)
- 在线编程(二)
- 三款热门入门级在线编程教程对比
- 笔试编程经典(leetcode在线编程)
- 运营商网络中的"在线"加密(三)
- 赛码网—在线编程(一)股神
- 赛码网—在线编程(二)上台阶
- 赛码网—在线编程(四)路灯
- 华为机试在线编程(一)
- 华为机试在线编程(二)
- 剑指offer在线编程(一)
- 剑指offer在线编程(二)
- 剑指offer在线编程(四)
- leetcode在线编程---树(java)
- 编程修养(三)
- 原码和反码及补码之间关系
- python、scala、java分别实现在spark上实现WordCount
- 利用burpsite和sqlmap进行post注入
- How to list all tags of a docker image
- 三层登录实例总结
- 在线编程(三)
- 微信密码框提示下载并安装安全控件
- jQuery源码中的“new jQuery.fn.init()”什么意思?
- LPCXpresso生成bin文件的方法及一些命令设置(图文并貌)----自己加备注!!!
- 经典vim插件功能说明、安装方法和使用方法介绍
- 虚拟机下安装tensorflow
- CQLSH安装教程
- win7 64bit 系统安装docker
- 线程与线程池