题目1(跳台阶)
描述
一只青蛙一次可以跳上 1 级台阶,也可以跳上 2 级。求该青蛙跳上一个 n 级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
数据范围:1 \leq n \leq 401≤n≤40
要求:时间复杂度:O(n)O(n) ,空间复杂度: O(1)O(1)
示例 1
输入:
2
复制
返回值:
2
复制
说明:
青蛙要跳上两级台阶有两种跳法,分别是:先跳一级,再跳一级或者直接跳两级。因此答案为2
示例 2
输入:
7
复制
返回值:
21
收获
对于本题,前提只有 一次 1 阶或者 2 阶的跳法。
a. 如果两种跳法,1 阶或者 2 阶,那么假定第一次跳的是一阶,那么剩下的是 n-1 个台阶,跳法是 f (n-1);
b. 假定第一次跳的是 2 阶,那么剩下的是 n-2 个台阶,跳法是 f (n-2)
c. 由 a\b 假设可以得出总跳法为: f (n) = f (n-1) + f (n-2)
d. 然后通过实际的情况可以得出:只有一阶的时候 f (1) = 1 , 只有两阶的时候可以有 f (2) = 2
e. 可以发现最终得出的是一个斐波那契数列:
| 1, (n=1)
f(n) = | 2, (n=2)
| f (n-1)+f (n-2) ,(n>2,n 为整数)
代码
class Solution {
public:
int jumpFloor(int number) {
if(number<=1){
return 1;
}
int a=1;
int b=1;
int res=0;
for(int i=2;i<=number;i++){
res=(a+b);
a=b;
b=res;
}
return res;
}
};
题目2(最小花费爬楼梯)
描述
给定一个整数数组 cost \cost ,其中 cost[i]\cost[i] 是从楼梯第i \i 个台阶向上爬需要支付的费用,下标从 0 开始。一旦你支付此费用,即可选择向上爬一个或者两个台阶。
你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。
请你计算并返回达到楼梯顶部的最低花费。
示例 1
输入:
[2,5,20]
复制
返回值:
5
复制
说明:
你将从下标为1的台阶开始,支付5 ,向上爬两个台阶,到达楼梯顶部。总花费为5
示例 2
输入:
[1,100,1,1,1,90,1,1,80,1]
复制
返回值:
6
复制
说明:
你将从下标为 0 的台阶开始。
1.支付 1 ,向上爬两个台阶,到达下标为 2 的台阶。
2.支付 1 ,向上爬两个台阶,到达下标为 4 的台阶。
3.支付 1 ,向上爬两个台阶,到达下标为 6 的台阶。
4.支付 1 ,向上爬一个台阶,到达下标为 7 的台阶。
5.支付 1 ,向上爬两个台阶,到达下标为 9 的台阶。
6.支付 1 ,向上爬一个台阶,到达楼梯顶部。
总花费为 6 。
收获
代码
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param cost int整型vector
* @return int整型
*/
int minCostClimbingStairs(vector<int>& cost) {
// write code here
vector<int >dp(cost.size()+1,0);
for(int i=2;i<=cost.size();i++){
dp[i]=min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]);
}
return dp[cost.size()];
}
};
题目3(不同路径的数目1)
示例 1
输入:
2,1
复制
返回值:
1
复制
示例 2
输入:
2,2
复制
返回值:
2
复制
收获
代码
class Solution {
public:
/**
*
* @param m int整型
* @param n int整型
* @return int整型
*/
int uniquePaths(int m, int n) {
// write code here
if(m==1||n==1)
return 1;
return uniquePaths(m-1,n)+uniquePaths(m,n-1);
}
};
题目4(矩阵的最小路径和)
示例 1
输入:
[[1,3,5,9],[8,1,3,4],[5,0,6,1],[8,8,4,0]]
复制
返回值:
12
复制
示例 2
输入:
[[1,2,3],[1,2,3]]
复制
返回值:
7
收获
1:很大的收获是学会了对边缘数据的初始化
代码
class Solution {
public:
/**
*
* @param matrix int整型vector<vector<>> the matrix
* @return int整型
*/
int minPathSum(vector<vector<int> >& matrix) {
// write code here
int n=matrix.size();
int m=matrix[0].size();
vector<vector<int >> dp(n,vector<int>(m,0));
//dp[i][j]表示以当前i,j位置为结尾的最短路径
dp[0][0]=matrix[0][0];
for(int i=1;i<n;i++)
dp[i][0]=matrix[i][0]+dp[i-1][0];
for(int i=1;i<m;i++)
dp[0][i]=matrix[0][i]+dp[0][i-1];
for(int i=1;i<n;i++)
for(int j=1;j<m;j++){
dp[i][j]=matrix[i][j]+(dp[i-1][j]>dp[i][j-1]?dp[i][j-1]:dp[i-1][j]);
}
return dp[n-1][m-1];
}
};
题目5(兑换零钱1)
示例 1
输入:
[5,2,3],20
复制
返回值:
4
复制
示例 2
输入:
[5,2,3],0
复制
返回值:
0
复制
示例 3
输入:
[3,5],2
复制
返回值:
-1
收获
代码
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* 最少货币数
* @param arr int整型vector the array
* @param aim int整型 the target
* @return int整型
*/
int minMoney(vector<int>& arr, int aim) {
// write code here
if(aim==0)
return 0;
vector<int >dp(aim+1,aim+1);
dp[0]=0;
for(int i=1;i<=aim;i++)
for(int j=0;j<arr.size();j++){
//纸币的面额一定要小于当前要组成的aim值
if(arr[j]<=i)
dp[i]=min(dp[i],dp[i-arr[j]]+1);
}
return dp[aim]>aim?-1:dp[aim];
}
};
题目6(最长公共子序列二)
示例 1
输入:
“1A2C3D4B56”,“B1D23A456A”
复制
返回值:
“123456”
复制
示例 2
输入:
“abc”,“def”
复制
返回值:
“-1”
复制
示例 3
输入:
“abc”,“abc”
复制
返回值:
“abc”
复制
示例 4
输入:
“ab”,“”
复制
返回值:
“-1”
收获
代码
class Solution {
public:
/**
* longest common subsequence
* @param s1 string字符串 the string
* @param s2 string字符串 the string
* @return string字符串
*/
string LCS(string s1, string s2) {
// write code here
int n1=s1.size();
int n2=s2.size();
vector<vector<string >>dp(n1,vector<string>(n2,""));
//dp[i][j]表示当处理到s1的第i个元素和s2的第j个元素时公共子序列的长度
for(int i=0;i<n1;i++)
for(int j=0;j<n2;j++){
if(i==0||j==0){
if(s1[i]==s2[j])
dp[i][j]=s1[i];
}else if(s1[i]==s2[j]){
dp[i][j]=dp[i-1][j-1]+s1[i];
}else{
dp[i][j]=dp[i][j-1].size()>dp[i-1][j].size()?dp[i][j-1]:dp[i-1][j];
}
}
if(dp[n1-1][n2-1]=="")
return "-1";
return dp[n1-1][n2-1];
}
};
题目7(最长公共子串)
示例 1
输入:
“1AB2345CD”,“12345EF”
复制
返回值:
“2345”
复制
收获
1:使用pos记录 位置,max记录长度的方法
代码
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* longest common substring
* @param str1 string字符串 the string
* @param str2 string字符串 the string
* @return string字符串
*/
string LCS(string str1, string str2) {
// write code here
int n1=str1.size();
int n2=str2.size();
int max=0;
int pos=0;
vector<vector<int >>dp(n1+1,vector<int >(n2+1,0));
for(int i=1;i<=n1;i++)
for(int j=1;j<=n2;j++){
if(str1[i-1]==str2[j-1]){
dp[i][j]=dp[i-1][j-1]+1;
}else{
dp[i][j]=0;
}
if(dp[i][j]>max){
max=dp[i][j];
pos=i-1;
}
}
return str1.substr(pos-max+1,max);
}
};
题目8(把数字翻译成字符串)
示例 1
输入:
“12”
复制
返回值:
2
复制
说明:
2种可能的译码结果(”ab” 或”l”)
示例 2
输入:
“31717126241541717”
复制
返回值:
192
复制
说明:
192种可能的译码结果
收获
这道题主要是对 0 的处理,比如 00 这种是非法的,而 10 呢,则只有一种编码。
用 dp [i] 表示 s [0,…,i-1] 时的编码次数,那么:
如果 s [i-1] == ‘0’,dp [i] = 0,否则 dp [i] = dp [i-1];
接着再根据 s [i-1] s [i-2] 更新 dp [i]:
如果 s [i-1] == ‘1’,dp [i] += dp [i-2]
如果 s [i-1] == ‘2’&& s[i] <= 6,dp[i] += dp[i-2]
代码
class Solution {
public:
/**
* 解码
* @param nums string字符串 数字串
* @return int整型
*/
int solve(string nums) {
// write code here
if(nums.size()==0||nums=="0")
return 0;
vector<int >dp(nums.size()+1,0);
dp[0]=1;
dp[1]=nums[0]=='0'?0:1;
for(int i=2;i<=nums.size();i++){
dp[i]=nums[i-1]=='0'?0:dp[i-1];
if((nums[i-2]=='1')||((nums[i-2]=='2')&&(nums[i-1]<='6'))){
dp[i]+=dp[i-2];
}
}
return dp[nums.size()];
}
};
题目9(最长上升子序列1)
示例 1
输入:
[6,3,1,5,2,3,7]
复制
返回值:
4
复制
说明:
该数组最长上升子序列为 [1,2,3,7] ,长度为4
收获
代码
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* 给定数组的最长严格上升子序列的长度。
* @param arr int整型vector 给定的数组
* @return int整型
*/
int LIS(vector<int>& arr) {
// write code here
int n=arr.size();
if(n==0)
return 0;
vector<int >dp(n,1);
//dp[i]表示遍历到i的时候的严格上升的子序列的长度
int res=0;
for(int i=1;i<n;i++)
for(int j=0;j<i;j++){
if(arr[i]>arr[j]&&dp[i]<dp[j]+1){
dp[i]=dp[j]+1;
res=max(res,dp[i]);
}
}
return res;
}
};
题目10(连续数组的最大和)
示例 1
输入:
[1,-2,3,10,-4,7,2,-5]
复制
返回值:
18
复制
说明:
经分析可知,输入数组的子数组[3,10,-4,7,2]可以求得最大和为18
示例 2
输入:
[2]
复制
返回值:
2
复制
示例 3
输入:
[-10]
复制
返回值:
-10
收获
1:这里很重要的是不是直接返回dp[n-1],是需要在过程中寻找最大值的~
代码
class Solution {
public:
int FindGreatestSumOfSubArray(vector<int> array) {
vector<int >dp(array.size(),0);
dp[0]=array[0];
int maxN=dp[0];
for(int i=1;i<array.size();i++){
dp[i]=max(dp[i-1]+array[i],array[i]);
maxN=max(maxN,dp[i]);
}
return maxN;
}
};