376.摆动序列
感觉没什么,就是检测拐点
class Solution {
public:
int wiggleMaxLength(vector<int>& nums) {
//0 is equal,
//1 is up,
//2 is down
//-1 is uninialize
int is_up = -1;
vector<int> reslut;
if(nums.size() < 1){
return nums.size();
}
int fisrt = nums.at(0);
for(int i=0; i<nums.size(); i++){
int current = nums.at(i);
int next;
if(i + 1 < nums.size()){
next = nums.at(i+1);
}
else{
break;
}
if(is_up == -1){
if(next > current){
is_up = 1;
reslut.push_back(fisrt);
}
if(next < current){
is_up = 2;
reslut.push_back(fisrt);
}
}
if(is_up == 1){
if(next >= current){
continue;
}
else{
reslut.push_back(current);
is_up = 2;
}
}
if(is_up == 2){
if(next > current){
reslut.push_back(current);
is_up = 1;
}
else{
continue;
}
}
}
int last_value = nums.at(nums.size() - 1);
reslut.push_back(last_value);
return reslut.size();
}
};
效率不是很高
class Solution {
public:
int fib(int n) {
if(n <= 0){
return 0;
}
if(n == 1){
return 1;
}
if(n > 1){
return fib(n-1) + fib(n-2);
}
return 0;
}
};
70.爬楼梯
使用递归比较耗时,能不用尽量不用,虽然比较好理解
class Solution {
private:
int dp[50];
public:
int climbStairs(int n) {
dp[1]=1;
dp[2]=2;
for(int i=3; i<=n; i++){
dp[i]=dp[i-1] + dp[i-2];
}
return dp[n];
}
};
746.使用最小花费爬楼梯
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost) {
int count = cost.size() - 1;
int bt_cost[1000];
bt_cost[0] = cost.at(0);
if(count < 1){
return cost.at(0);
}
bt_cost[1] = std::min(bt_cost[0], cost.at(1));
if(count < 2){
return bt_cost[count];
}
bt_cost[2] = std::min(bt_cost[0]+cost.at(2), cost.at(1));
for(int i=3; i<cost.size(); i++){
bt_cost[i] = std::min(bt_cost[i-1] + cost.at(i),
bt_cost[i-2] + cost.at(i-1));
}
return bt_cost[count];
}
};
62.不同路径
class Solution {
public:
int uniquePaths(int m, int n) {
int data[m][n];
for(int i=0; i<m;i++){
for(int j=0; j<n; j++){
if(i == 0 || j == 0){
data[i][j] = 1;
continue;
}
data[i][j] = data[i-1][j] + data[i][j-1];
}
}
return data[m-1][n-1];
}
};
63.不同路径2
class Solution {
public:
int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
int m = obstacleGrid.size();
int n = obstacleGrid.at(0).size();
int data[m][n];
if(obstacleGrid.at(0).at(0) == 1){
data[0][0] = 0;
}
else{
data[0][0] = 1;
}
for(int i=0; i<m;i++){
for(int j=0; j<n; j++){
if(obstacleGrid.at(i).at(j) == 1){
data[i][j] = 0;
continue;
}
int part_1 = 0;
if(i-1 >= 0){
part_1 = data[i-1][j];
}
int part_2 = 0;
if(j-1 >=0){
part_2 = data[i][j-1];
}
if(i==0 && j==0){
continue;
}
else{
data[i][j] = part_1 + part_2;
}
}
}
return data[m-1][n-1];
}
};
343.整数拆分
class Solution {
public:
int integerBreak(int n) {
if(n==1){
return 0;
}
if(n==2){
return 1;
}
if(n==3){
return 2;
}
//else
int result[n+1];
result[1] = 0;
result[2] = 2;
result[3] = 3;
result[4] = 4;
for(int i=5; i<=n; i++){
int time = n/3;
int last = n%3;
if(last == 1){
time--;
last += 3;
}
result[i] = 1;
while(time > 0){
result[i] *= 3;
time--;
}
if(last == 0){
return result[i];
}
else{
result[i] *= result[last];
}
}
return result[n];
}
};
96.不同的二叉搜索树
class Solution {
public:
int numTrees(int n) {
if(n==1){
return 1;
}
int tree_num[n+1];
tree_num[0] = 1;
tree_num[1] = 1;
tree_num[2] = 2;
for(int i=3; i<=n; i++){
tree_num[i] = 0;
for(int j=1; j<=i; j++){
int left = j-1;
int right = i-j;
tree_num[i] += (tree_num[left]*tree_num[right]);
}
}
return tree_num[n];
}
};
416 分割等和子集
class Solution {
public:
bool canPartition(vector<int>& nums) {
int sum = 0;
for(auto it : nums){
sum += it;
}
if(sum%2 != 0) return false;
int target = sum/2;
int bag[nums.size()][target+1];
int first = nums.at(0);
for(int j=0; j<target+1; j++){
bag[0][j] = 0;
if(j == first){
bag[0][j] = 1;
}
}
for(int i=1; i<nums.size(); i++){
int value = nums.at(i);
for(int j=0; j<target+1; j++){
if(bag[i-1][j] == 0){
if(value <= target && value == j){
bag[i][j] = 1;
}
else{
if(bag[i][j] == 1){
continue;
}
else{
bag[i][j] = 0;
}
}
}
else{
int value_new = j + value;
bag[i][j] = 1;
if(value_new <= target){
bag[i][value_new] = 1;
}
}
if(bag[i][target] == 1){
return true;
}
}
}
if(bag[nums.size()-1][target] == 1){
return true;
}
else{
return false;
}
}
};
494.目标和
class Solution {
public:
int total_num = 0;
void backtrace(vector<int>& nums, int sum, int index, int target){
int value = 0;
if(index == nums.size() - 1 ){
value = nums.at(index);
if((sum+value) == target){
total_num++;
}
if((sum-value) == target){
total_num++;
}
return;
}
else{
value = nums.at(index);
backtrace(nums, sum+value, index+1, target);
backtrace(nums, sum+value*(-1), index+1, target);
}
}
int findTargetSumWays(vector<int>& nums, int target) {
backtrace(nums, 0, 0, target);
return total_num;
}
};
377.组合总和4
中途会有超出的情况,不计算即可。
class Solution {
public:
//0 1 2 3 4 5
//1
// 1
// 2
// 4
// 7
// 10
int combinationSum4(vector<int>& nums, int target) {
const int a = target + 1;
int bag[a];
for(int i=1; i<a; i++){
bag[i] = 0;
}
bag[0] = 1;
for(int i=1; i<=target; i++){
for(int j=0; j<nums.size(); j++){
if(i>=nums.at(j) && bag[i] < INT_MAX-bag[i-nums.at(j)]){
//if(bag[i] > INT_MAX-bag[i-nums.at(j)]){
// return bag[i];
//}
bag[i] += bag[i-nums.at(j)];
}
}
}
return bag[321];
}
};
322.零钱兑换
自己通过的第一个复杂一些的动态规划
class Solution {
public:
//1 2 3 4 5 6 7 8 9 10 11
//1 1 2 2 1 2 2 3 3 2 1
int coinChange(vector<int>& coins, int amount) {
if(amount == 0){
return 0;
}
int dp[amount+1];
for(int i=0; i<amount+1; i++){
dp[i] = 0;
}
for(int i=0; i<coins.size(); i++){
int value = coins.at(i);
if(value > amount){
continue;
}
dp[value] = 1;
}
for(int i=0; i<amount+1; i++){
if(dp[i] != 0){
continue;
}
int min_value = amount;
for(int j=0; j<coins.size(); j++){
if(i>coins.at(j)){
if(dp[i-coins.at(j)] == 0){
//dp[i] = -1;
continue;
}
dp[i] = dp[i-coins.at(j)] + 1;
if(dp[i] < min_value){
min_value = dp[i];
}
}
}
dp[i] = std::min(min_value,dp[i]);
}
if(dp[amount] == 0){
return -1;
}
return dp[amount];
}
};
279.完全平方数
class Solution {
public:
//1 4 9 16
//1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
//1 2 3 1 2 3 4 2 1 1
int numSquares(int n) {
int dp[n+1];
for(int i=0; i<n+1; i++){
dp[i] = 0;
}
int d=1;
while(d*d <= n){
dp[d*d] = 1;
d++;
}
for(int i=2; i<n+1; i++){
if(dp[i] != 0){
continue;
}
int min_count = n;
for(int j=1; j<n+1; j++){
if(i > j*j){
dp[i] = dp[i-j*j] + dp[j*j];
if(dp[i] < min_count){
min_count = dp[i];
}
}
else{
break;
}
}
dp[i] = std::min(dp[i], min_count);
}
return dp[n];
}
};
139.单词拆分
不是自己写的,官方的版本
class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict) {
auto wordDictSet = unordered_set<string>();
for(auto word: wordDict){
wordDictSet.insert(word);
}
auto dp = vector<bool>(s.size()+1);
dp[0] = true;
for(int i=1; i<=s.size()+1; i++){
for(int j=0; j<i; j++){
if(dp[j] == true
&& wordDictSet.find(s.substr(j,i-j)) != wordDictSet.end()){
dp[i] = true;
break;
}
}
}
return dp[s.size()];
}
};
121.买卖股票的最佳时机
感觉和动规没有关系
class Solution {
public:
// dp[0] 0 7 7
// dp[1] 0 1 0
// dp[2] 4 1 4
// dp[3] 3 1 2
int maxProfit(vector<int>& prices) {
int max_monry = 0;
int min_value = INT_MAX;
int money = 0;
for(int i=0; i<prices.size(); i++){
if(prices.at(i) < min_value){
min_value = prices.at(i);
}
if(prices.at(i) > min_value){
money = prices.at(i) - min_value;
if(money > max_monry){
max_monry = money;
}
}
}
return max_monry;
}
};
122.买卖股票的最佳时机2
官方的,这么简单,自己写的还要检测上升和下降
class Solution {
public:
int maxProfit(vector<int>& prices) {
int reault = 0;
for(int i=1; i<prices.size(); i++){
reault += max(prices[i] - prices[i-1], 0);
}
return reault;
}
};
123.买卖股票的最佳时机
参考官网
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n = prices.size();
int buy1 = -prices[0], sell1 = 0;
int buy2 = -prices[0], sell2 = 0;
for (int i = 1; i < n; ++i) {
buy1 = max(buy1, -prices[i]);
sell1 = max(sell1, buy1 + prices[i]);
buy2 = max(buy2, sell1 - prices[i]);
sell2 = max(sell2, buy2 + prices[i]);
}
return sell2;
}
};
388.买股票的最佳时机4
自己写的开窍版本
class Solution {
public:
int maxProfit(int k, vector<int>& prices) {
int n = prices.size();
int buy[k];
int sell[k];
for(int i=0; i<k; i++){
buy[i] = -prices[0];
sell[i] = 0;
}
for (int i = 1; i < n; ++i) {
buy[0] = max(buy[0], -prices[i]);
sell[0] = max(sell[0], buy[0] + prices[i]);
for(int j=0; j<k-1; j++){
buy[j+1] = max(buy[j+1], sell[j] - prices[i]);
sell[j+1] = max(sell[j+1], buy[j+1] + prices[i]);
}
}
return sell[k-1];
}
};
714.买卖股票的最佳时机含手续费
自己写的,过了
class Solution {
public:
// dp[i][0] dp[i+1][0] //0 持有股票
// dp[i][1] dp[i+1][1] //1 卖出股票
// dp[0][0] = 0; //0 没有持有股票
// dp[0][1] = -prices(0); //1 买入股票
// dp[0][2] = 0; //2 卖出股票
// dp[1][0] = max(dp[0][2], dp[0][0])
// dp[1][1] = max(dp[0][0]-prices(i), dp[0][1], dp[0][2]-prices(i));
// dp[1][2] = dp[0][1] + prices(i) - fee;
int maxProfit(vector<int>& prices, int fee) {
int dp[prices.size()][3];
dp[0][0] = 0;
dp[0][1] = -prices.at(0);
dp[0][2] = 0;
for(int i=1; i<prices.size(); i++){
dp[i][0] = max(dp[i-1][2], dp[i-1][0]);
dp[i][1] = max(max(dp[i-1][0]-prices.at(i),
dp[i-1][1]),
dp[i-1][2]-prices.at(i));
dp[i][2] = dp[i-1][1] + prices.at(i) - fee;
}
return max(dp[prices.size()-1][0], dp[prices.size()-1][2]);
}
};
300.最长递增子序列
最笨方法
class Solution {
public:
// dp[0] 1
// dp[1] 2
// dp[2] 2
// dp[3] 3
// dp[4] 3
// dp[5] 3
// dp[6] 4
int lengthOfLIS(vector<int>& nums) {
int dp[nums.size()];
dp[0] = 1;
int max_count = 1;
for(int i=1; i<nums.size(); i++)
{
dp[i] = 1;
for(int j=i-1; j>=0; j--){
if(nums.at(i) > nums.at(j)){
dp[i] = max(dp[j]+1, dp[i]);
if(dp[i] > max_count){
max_count = dp[i];
}
}
}
}
return max_count;
}
};
感觉不用递归
class Solution {
public:
int findLengthOfLCIS(vector<int>& nums) {
int up_step = 1;
int max_up_step = 0;
for(int i=1; i<nums.size(); i++){
if(nums.at(i) > nums.at(i-1)){
up_step++;
}
else{
max_up_step = max(max_up_step, up_step);
up_step = 1;
}
}
max_up_step = max(max_up_step, up_step);
return max_up_step;
}
};
动规效率也一般,不是自己写的
class Solution {
public:
int findLength(vector<int>& A, vector<int>& B) {
int n = A.size(), m = B.size();
vector<vector<int>> dp(n + 1, vector<int>(m + 1, 0));
int ans = 0;
for (int i = n - 1; i >= 0; i--) {
for (int j = m - 1; j >= 0; j--) {
dp[i][j] = A[i] == B[j] ? dp[i + 1][j + 1] + 1 : 0;
ans = max(ans, dp[i][j]);
}
}
return ans;
}
};
1143.最长公共子序列
更像找规律
class Solution {
public:
int longestCommonSubsequence(string text1, string text2) {
int m = text1.length(), n = text2.length();
vector<vector<int>> dp(m + 1, vector<int>(n + 1));
for (int i = 1; i <= m; i++) {
char c1 = text1.at(i - 1);
for (int j = 1; j <= n; j++) {
char c2 = text2.at(j - 1);
if (c1 == c2) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
return dp[m][n];
}
};
0 1 2 3 4 5 6
0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0
2 1 1 1 1 1 1 1
3 1 1 1 1 1 2 2
4 1 1 1 1 1 2 2
5 1 1 1 2 2 2 2
1035.不相交的线
同上,只是换了一种形式
class Solution {
public:
int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2) {
int m = nums1.size(), n = nums2.size();
vector<vector<int>> dp(m + 1, vector<int>(n + 1));
for (int i = 1; i <= m; i++) {
int c1 = nums1.at(i - 1);
for (int j = 1; j <= n; j++) {
int c2 = nums2.at(j - 1);
if (c1 == c2) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
return dp[m][n];
}
};
392.判断子序列
没有用动规
class Solution {
public:
bool isSubsequence(string s, string t) {
int i = 0;
int j = 0;
while(j<t.length() && i<s.length()){
if(s[i] == t[j]){
i++;
j++;
}
else{
j++;
}
}
if(i == s.length()){
return true;
}
else{
return false;
}
}
};
最长公共子序列的翻版
class Solution {
public:
int minDistance(string word1, string word2) {
int m = word1.length(), n = word2.length();
vector<vector<int>> dp(m + 1, vector<int>(n + 1));
for (int i = 1; i <= m; i++) {
char c1 = word1.at(i - 1);
for (int j = 1; j <= n; j++) {
char c2 = word2.at(j - 1);
if (c1 == c2) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
return word1.length() + word2.length() -2*dp[m][n];
}
};
72.编辑距离
动规是如何发现的呢?抄官方
class Solution {
public:
int minDistance(string word1, string word2) {
int n = word1.length();
int m = word2.length();
// 有一个字符串为空串
if (n * m == 0) return n + m;
// DP 数组
vector<vector<int>> D(n + 1, vector<int>(m + 1));
// 边界状态初始化
for (int i = 0; i < n + 1; i++) {
D[i][0] = i;
}
for (int j = 0; j < m + 1; j++) {
D[0][j] = j;
}
// 计算所有 DP 值
for (int i = 1; i < n + 1; i++) {
for (int j = 1; j < m + 1; j++) {
int left = D[i - 1][j] + 1;
int down = D[i][j - 1] + 1;
int left_down = D[i - 1][j - 1];
if (word1[i - 1] != word2[j - 1]) left_down += 1;
D[i][j] = min(left, min(down, left_down));
}
}
return D[n][m];
}
};
516.最长回文子序列
想出来这个方法的人,智商best
class Solution {
public:
int longestPalindromeSubseq(string s) {
int n = s.length();
vector<vector<int>> dp(n, vector<int>(n));
for (int i = n - 1; i >= 0; i--) {
dp[i][i] = 1;
char c1 = s[i];
for (int j = i + 1; j < n; j++) {
char c2 = s[j];
if (c1 == c2) {
dp[i][j] = dp[i + 1][j - 1] + 2;
} else {
dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);
}
}
}
return dp[0][n - 1];
}
}; 3 4 44 33
j b b b a b
i 0 1 2 3 4
b 0 1 2 3 3 4
b 1 1 2 2 3
b 2 1 1 3
a 3 1 1
b 4 1