目录
[买卖股票的最佳时机 III](#买卖股票的最佳时机 III)
[买卖股票的最佳时机 IV](#买卖股票的最佳时机 IV)
零钱兑换
解法:完全背包
记得是找最小兑换个数,初始化为 0x3f3f3f3,不然会栈溢出
cpp
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
if(amount == 0)
{
return 0;
}
int n = coins.size();
vector<vector<int>> dp(n + 1, vector<int>(amount + 1, 0x3f3f3f3f));
for(int i = 0; i <= n; i++)
{
dp[i][0] = 0;
}
for(int i = 1;i <= n; i++)
{
for(int j = 1; j <= amount; j++)
{
dp[i][j] = dp[i-1][j];
if(j >= coins[i-1])
{
dp[i][j] = min(dp[i][j],dp[i][j-coins[i-1]] + 1);
}
}
}
return dp[n][amount] == 0x3f3f3f3f ? -1:dp[n][amount];
}
};
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
if(amount == 0)
{
return 0;
}
int n = coins.size();
vector<int> dp(amount + 1, 0x3f3f3f3f);
dp[0] = 0;
for(int i = 1;i <= n; i++)
{
for(int j = 1; j <= amount; j++)
{
if(j >= coins[i-1])
{
dp[j] = min(dp[j],dp[j-coins[i-1]] + 1);
}
}
}
return dp[amount] == 0x3f3f3f3f ? -1:dp[amount];
}
};
解法二:贪心 + 二分
cpp
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int n = nums.size();
vector<int> ret;
for(int i = 0; i < n; i++)
{
if(ret.size() == 0 || ret.back() < nums[i])
{
ret.push_back(nums[i]);
}
else
{
int l = 0, r = ret.size() - 1;
while(l < r)
{
int mid = l + (r - l) / 2;
if(ret[mid] < nums[i])
{
l = mid + 1;
}
else
{
r = mid;
}
}
ret[l] = nums[i];
}
}
return ret.size();
}
};
三角形最小路径之和
解法:动态规划
二维动态规划,根据题目所给条件构建动态转移方程来解决,注意列j的取值范围
cpp
class Solution {
public:
int minimumTotal(vector<vector<int>>& triangle) {
int n = triangle.size();
vector<vector<int>> dp(n + 1,vector<int>(n + 1, 0x3f3f3f3f));
dp[0][0] = 0;
int ret = 0x3f3f3f3f;
for(int i = 1;i <= n;i++)
{
for(int j = 1;j <=i; j++)
{
dp[i][j] = min(dp[i-1][j],dp[i-1][j-1]) + triangle[i-1][j-1];
if(i == n)
{
ret = min(ret,dp[i][j]);
}
}
}
return ret;
}
};
最小路径和
解法:动态规划
路径问题的二维dp模型:取上和左的值来求最小路径和
cpp
class Solution {
public:
int minPathSum(vector<vector<int>>& grid) {
int n = grid.size(), m =grid[0].size();
vector<vector<int>> dp(n + 1, vector<int>(m + 1, INT_MAX));
dp[0][1] = 0;
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= m; j++)
{
dp[i][j] = min(dp[i-1][j], dp[i][j - 1]) + grid[i-1][j-1];
}
}
return dp[n][m];
}
};
不同路径二
解法:动态规划
与上题思路类似
cpp
class Solution {
public:
int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
int n = obstacleGrid.size(), m =obstacleGrid[0].size();
vector<vector<int>> dp(n + 1, vector<int>(m + 1, 0));
dp[0][1] = 1;
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= m; j++)
{
if(obstacleGrid[i - 1][j - 1] == 0)
{
dp[i][j] = dp[i-1][j] + dp[i][j-1];
}
}
}
return dp[n][m];
}
};
最长回文子串
解法:动态规划
使用dpij 来表示:s 的【i,j】位置构成的子串是否是回文串,再进行遍历找最长的
cpp
class Solution {
public:
string longestPalindrome(string s) {
int n = s.size();
vector<vector<bool>> dp(n,vector<bool>(n,false));
for(int i = n - 1; i >=0 ; i--)
{
for(int j = i; j < n ; j++)
{
if(s[i] == s[j])
{
if(i == j || i + 1 == j || dp[i + 1][j - 1])
{
dp[i][j] = true;
}
}
}
}
string ret;
int len = 0;
for(int i = 0; i < n; i++)
{
for(int j = i; j < n; j++)
{
if(dp[i][j] && len < j - i + 1)
{
len = max(len, j - i + 1);
ret = s.substr(i, len);
}
}
}
return ret;
}
};
交错字符串
解法:动态规划
往二维dp字符串的思路上想
cpp
class Solution {
public:
bool isInterleave(string s1, string s2, string s3) {
int n = s1.size(), m = s2.size(), k = s3.size();
if(n + m != k)
{
return false;
}
vector<vector<bool>> dp(n + 1, vector<bool>(m + 1, false));
s1 = " " + s1,s2 = " " + s2,s3 = " " + s3;
dp[0][0] = true;
for(int i = 1; i <= n; i++)
{
if(s1[i] != s3[i]) break;
else dp[i][0] = true;
}
for(int j = 1; j <= m; j++)
{
if(s2[j] != s3[j]) break;
else dp[0][j] = true;
}
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= m; j++)
{
if((dp[i-1][j] && s1[i] == s3[i + j]) || (dp[i][j-1] && s2[j] == s3[i + j]))
{
dp[i][j] = true;
}
}
}
return dp[n][m];
}
};
// 一维很多坑
class Solution {
public:
bool isInterleave(string s1, string s2, string s3) {
int n = s1.size(), m = s2.size(), k = s3.size();
if(n + m != k)
{
return false;
}
vector<bool> dp(m + 1, false);
s1 = " " + s1,s2 = " " + s2,s3 = " " + s3;
dp[0] = true;
// for(int i = 1; i <= n; i++)
// {
// if(s1[i] != s3[i]) break;
// else dp[i][0] = true;
// }
for(int j = 1; j <= m; j++)
{
//if(s2[j] != s3[j]) break;
if(s2[j] != s3[j] || dp[j - 1] == false) break;
else dp[j] = true;
}
for(int i = 1; i <= n; i++)
{
// 放在填表中更新第一行
dp[0] = dp[0] && (s1[i] == s3[i]);
// dp[i][0] = dp[i-1][0] && (s1[i] == s3[i]);
for(int j = 1; j <= m; j++)
{
if((dp[j] && (s1[i] == s3[i + j])) || (dp[j-1] && (s2[j] == s3[i + j])))
{
dp[j] = true;
}
else
{
// 还要加上else判断。。。。
dp[j] = false;
}
}
}
return dp[m];
}
};
编辑距离
解法:动态规划
注意初始化
cpp
class Solution {
public:
int minDistance(string word1, string word2) {
int n = word1.size(), m = word2.size();
vector<vector<int>> dp(n + 1,vector<int>(m + 1));
// 初始化 0表示空串
for(int i = 0; i <= n; i++)
{
dp[i][0] = i;
}
for(int j = 0; j <= m; j++)
{
dp[0][j] = j;
}
for(int i = 1; i <= n; i++)
{
for(int j = 1;j <=m; j++)
{
if(word1[i-1] == word2[j-1]) dp[i][j] = dp[i-1][j-1];
else
{
dp[i][j] = min(dp[i-1][j-1],min(dp[i-1][j],dp[i][j-1])) + 1;
}
}
}
return dp[n][m];
}
};
买卖股票的最佳时机 III
买卖股票的最佳时机 IV
解法:动态规划
做了n多次,到这里还是实现出来有点问题,空悲切··
cpp
// 3 换 k+1 解决IV问题
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n = prices.size();
vector<vector<int>> bug(n, vector<int>(3, -0x3f3f3f3f));
vector<vector<int>> solt(n, vector<int>(3,-0x3f3f3f3f));
bug[0][0] = -prices[0];
solt[0][0] = 0;
for(int i = 1; i < n; i++)
{
for(int j = 0; j < 3; j++)
{
bug[i][j] = max(bug[i-1][j], solt[i-1][j] - prices[i]);
solt[i][j] = solt[i-1][j];
if(j-1>=0)
{
solt[i][j] = max(solt[i][j],bug[i-1][j-1] + prices[i]);
}
}
}
int ans=0;
for(int j = 0; j < 3; j++)
{
ans = max(ans, solt[n-1][j]);
}
return ans;
}
};
最大正方形
解法:动态规划
状态定义:dpij 表示 当前正方形的最大边长;怎么得到?
上 左 左上角的正方形的最大边长的最小值,但是还要判断是否可以跟当前位置进行结果:当前位置为1,可以跟最小值 + 1 组成更大的;为0就只能为0,结果都结果不了
cpp
class Solution {
public:
int maximalSquare(vector<vector<char>>& matrix) {
int n = matrix.size(), m = matrix[0].size();
int ret = 0;
vector<vector<int>> dp(n+1,vector<int>(m+1,INT_MAX));
for(int i=0;i<n;i++) dp[i][0]=0;
for(int j=0;j<m;j++) dp[0][j]=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(matrix[i-1][j-1] == '1')
{
dp[i][j] = min(dp[i-1][j],min(dp[i][j-1],dp[i-1][j-1])) + 1;
}
else
{
dp[i][j] = 0;
}
ret = max(ret,dp[i][j] * dp[i][j]);
}
}
return ret;
}
};
以上便是全部内容,有问题欢迎在评论区指正,感谢观看!