【c/c++算法刷题笔记】—— LeetCode打卡09


【前言】OJ:AcWing + LeetCode 。活动:b站 大雪菜 。

动态规划02

1 最长上升子序列

题目描述

给定一个无序的整数数组,找到其中最长上升子序列的长度。

说明:

可能会有多种最长上升子序列的组合,你只需要输出对应的长度即可。
你算法的时间复杂度应该为 O(n2) 。

样例

示例:

输入: [10,9,2,5,3,7,101,18]
输出: 4
解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。

笔记

在这里插入图片描述

代码
/*
    法一:DP
    法二:贪心


*/
class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        int n=nums.size();
        vector<int> f(n);  //以i为下标时,最长子序列长度
        for(int i=0;i<n;i++){   
            f[i]=1;             //只有 i 自己时
            for(int j=0;j<i;j++){
                if(nums[j]<nums[i]) f[i]=max(f[i],f[j]+1);
            }
        }
        int res=0;
        for(int i=0;i<n;i++)
            res= res>f[i]?res:f[i];
        
        return res;
    }
};

2 编辑距离

题目描述

给定两个单词 word1 和 word2,计算出将 word1 转换成 word2 所使用的最少操作数 。

你可以对一个单词进行如下三种操作:

插入一个字符
删除一个字符
替换一个字符

样例

示例 1:

输入: word1 = “horse”, word2 = “ros”
输出: 3
解释:
horse -> rorse (将 ‘h’ 替换为 ‘r’)
rorse -> rose (删除 ‘r’)
rose -> ros (删除 ‘e’)

示例 2:

输入: word1 = “intention”, word2 = “execution”
输出: 5
解释:
intention -> inention (删除 ‘t’)
inention -> enention (将 ‘i’ 替换为 ‘e’)
enention -> exention (将 ‘n’ 替换为 ‘x’)
exention -> exection (将 ‘n’ 替换为 ‘c’)
exection -> execution (插入 ‘u’)

笔记

在这里插入图片描述

代码
class Solution {
public:
    int minDistance(string word1, string word2) {
        int n=word1.size(),m=word2.size();
        vector<vector<int>> f(n+1,vector<int>(m+1));
        for(int i=0;i<=n;i++) f[i][0]=i;
        for(int i=0;i<=m;i++) f[0][i]=i;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                f[i][j]=min(f[i-1][j],f[i][j-1])+1;
                f[i][j]=min(f[i][j],f[i-1][j-1]+(word1[i-1]!=word2[j-1]));
            }
        }
        return f[n][m];
    }
};

3 零钱兑换 II

题目描述

给定不同面额的硬币和一个总金额。写出函数来计算可以凑成总金额的硬币组合数。假设每一种面额的硬币有无限个。

注意:

你可以假设:

0 <= amount (总金额) <= 5000
1 <= coin (硬币面额) <= 5000
硬币种类不超过 500 种
结果符合 32 位符号整数

样例

示例 1:

输入: amount = 5, coins = [1, 2, 5]
输出: 4
解释: 有四种方式可以凑成总金额:
5=5
5=2+2+1
5=2+1+1+1
5=1+1+1+1+1

示例 2:

输入: amount = 3, coins = [2]
输出: 0
解释: 只用面额2的硬币不能凑成总金额3。

示例 3:

输入: amount = 10, coins = [10]
输出: 1

笔记

在这里插入图片描述
化简:
在这里插入图片描述
在这里插入图片描述

代码
/*
    完全背包问题 f[j] 当总金额为j时,硬币组合方式
*/class Solution {
public:
    int change(int m, vector<int>& coins) {
        int n=coins.size();
        vector<int> f(m+1);
        f[0]=1;
        for(auto c:coins){
            for(int j=c;j<=m;j++){
                f[j]=f[j]+f[j-c];
            }
        }
        return f[m];
    }
};

4 奇怪的打印机

题目描述
样例
笔记
  1. 由数据范围反推算法复杂度以及算法内容:https://www.acwing.com/blog/content/32/
  2. 在这里插入图片描述
代码
/*
     DP 要保证算每个状态时,所需条件都已经有值,所以从小到大遍历
*/
class Solution {
public:
    int strangePrinter(string s) {
        if(s.empty()) return 0;
        int n=s.size();
        vector<vector<int>> f(n+1,vector<int>(n+1));
        for(int len=1;len<=n;len++){
            for(int l=0;l+len-1<n;l++){
                int r=l+len-1;
                f[l][r]=f[l+1][r]+1;
                for(int k=l+1;k<=r;k++){
                    if(s[k]==s[l]) 
                        f[l][r]=min(f[l][r],f[l][k-1]+f[k+1][r]);
                }
            }
        }
        return f[0][n-1];
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值