LeetCode刷题day1

LeetCode刷题day1

LCR 095. 最长公共子序列

给定两个字符串 text1text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 0

一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。

  • 例如,"ace""abcde" 的子序列,但 "aec" 不是 "abcde" 的子序列。

两个字符串的 公共子序列 是这两个字符串所共同拥有的子序列。

示例 1:

输入:text1 = "abcde", text2 = "ace" 
输出:3  
解释:最长公共子序列是 "ace" ,它的长度为 3 。

示例 2:

输入:text1 = "abc", text2 = "abc"
输出:3
解释:最长公共子序列是 "abc" ,它的长度为 3 。

示例 3:

输入:text1 = "abc", text2 = "def"
输出:0
解释:两个字符串没有公共子序列,返回 0 。

提示:

  • 1 <= text1.length, text2.length <= 1000
  • text1text2 仅由小写英文字符组成。

分析:

这是一道动态规划题,LCS,它不要求连续,只要求顺序,这有点像最长字串问题,但是,是否感觉更有意思?

在这里插入图片描述

s1 = "abcde", s2 = "ace"

1. 定义:D[i][j]定义为s1前i个字符 与 s2前j个字符的LCS。
2. 分解:从最终状态往前推演。

①末尾能匹配上:D[i][j] = 1 +D[i-1][j-1]
在这里插入图片描述

②末尾不能匹配上: 丢掉s1末尾:D[i][j] = D[i-1][j]

			   丢掉`s2`末尾:`D[i][j] = D[i][j-1] `

谁效果好留下谁。即:D[i][j] = max( D[i][j-1], D[i][j-1])

3.子问题
  • D00 = 0
  • D0j = 0
  • Di0 =0

请添加图片描述
在这里插入图片描述

上代码:

class Solution {
    //注意i,j对应问题
public:
    int longestCommonSubsequence(string s1, string s2) {
        int d[1000][1000];
    
    for(int i=0;i<1000;i++){
        for(int j=0;j<1000;j++)
            d[i][j]=0;
    }
    int LCS=0;
    for(int i=1;i<=s1.length();i++) {
        for(int j=1;j<=s2.length();j++) {
            if(s1[i-1]==s2[j-1]) {//i-1,j-1
                d[i][j]=d[i-1][j-1]+1;
            }
            else {
                d[i][j]= max(d[i-1][j],d[i][j-1]);
            }
            if(LCS<d[i][j]) {
                LCS=d[i][j];
            }
        }
    }
    return LCS;//找到最大值,其实右下角,一定是最大值

    }
};

416. 分割等和子集

给你一个 只包含正整数非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。

示例 1:

输入:nums = [1,5,11,5]
输出:true
解释:数组可以分割成 [1, 5, 5] 和 [11] 。

示例 2:

输入:nums = [1,2,3,5]
输出:false
解释:数组不能分割成两个元素和相等的子集。

提示:

  • 1 <= nums.length <= 200
  • 1 <= nums[i] <= 100

分析:

这就是个01背包问题。

什么是01背包问题?

在这里插入图片描述

在这里插入图片描述

题解

本题就是把数组一分为二,且是均分。因此,如果数组累加和为奇数,肯定不行。注意题目的范围,注意调整。

代码:

class Solution {
public:
    bool canPartition(vector<int>& nums) {
        int c=0;
        for (int i = 0; i < nums.size(); i++)
            c+=nums[i];
        if(c%2!=0)//先排除一部分
            return false ;    
        c/=2;
        int m=c+3;
        int d[201][m];
        for(int i=0;i<201;i++){
            for(int j=0;j<m;j++)//注意界限,直接开大数组,容易超时
            if(i==0||j==0)
            d[i][j]=0;
        }
        for (int i = 1; i <= nums.size(); i++) {
            for (int j = 1; j <=c ; j++) {
                if(nums[i-1]>j){//can't,直接放不进去
                    d[i][j]=d[i-1][j];
                }
                else{
                    d[i][j]=max(nums[i-1]+d[i-1][j-nums[i-1]],d[i-1][j]);
                }
            }
        }
         for(int i=1;i<=nums.size();i++){
            for(int j=1;j<=c;j++)
            if(d[i][j]==c)//d[i][j]装的就是数字和,也就是value价值,就是c;通俗讲,d[i][j]求出的就是能拿进背包的数字,他们的价值=1/2全部,剩下的自然也是1/2全部
                return true;
        }
        return false;

        }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值