首页 > 其他分享 >20天 hot 100 速通计划-day18

20天 hot 100 速通计划-day18

时间:2023-08-28 21:12:22浏览次数:43  
标签:20 速通 nums int min 示例 hot 数组 dp

动态规划

139. 单词拆分

给你一个字符串 s 和一个字符串列表 wordDict 作为字典。请你判断是否可以利用字典中出现的单词拼接出 s

注意:不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。

示例 1:

输入: s = "leetcode", wordDict = ["leet", "code"]
输出: true
解释: 返回 true 因为 "leetcode" 可以由 "leet" 和 "code" 拼接成。

示例 2:

输入: s = "applepenapple", wordDict = ["apple", "pen"]
输出: true
解释: 返回 true 因为 "applepenapple" 可以由 "apple" "pen" "apple" 拼接成。
     注意,你可以重复使用字典中的单词。

示例 3:

输入: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]
输出: false

提示:

  • 1 <= s.length <= 300
  • 1 <= wordDict.length <= 1000
  • 1 <= wordDict[i].length <= 20
  • swordDict[i] 仅由小写英文字母组成
  • wordDict 中的所有字符串 互不相同

完全背包特有结构模板

class Solution {
// “数”作物品,“和”作背包
// 单词任取 → 完全背包 → 内正序
// 看作排列问题 → 内清零,外定序 → 外背包
public:
    bool wordBreak(string s, vector<string>& wordDict) {
        unordered_set<string> wordSet(wordDict.begin(), wordDict.end());
        //定义:dp[容量]:字符串长度为 容量 的字符串能否被拆分成字典单词组合
        vector<int> dp(s.size() + 1, false);// 能取 s.size()
      	// 定初值:空串可以被拆分,因此dp[0]为true(意义角度:必要性)
        dp[0] = true; // 保证递归可进行(运算角度:可行性)
        for(int i = 1; i <= s.size(); i++){//外背包
            for(int j = 0; j < i; j++){
                string word = s.substr(j, i - j);
                if(wordSet.find(word) != wordSet.end() && dp[j]){
                    // [j,i] 能拆分,且 dp[j] 可拆分时为 true
                    dp[i] = true;
                }
            }
            
        }
        return dp[s.size()];
    }
};

300. 最长递增子序列

给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。

子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。

示例 1:

输入:nums = [10,9,2,5,3,7,101,18]
输出:4
解释:最长递增子序列是 [2,3,7,101],因此长度为 4 。

示例 2:

输入:nums = [0,1,0,3,2,3]
输出:4

示例 3:

输入:nums = [7,7,7,7,7,7,7]
输出:1

提示:

  • 1 <= nums.length <= 2500
  • -104 <= nums[i] <= 104
class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        // 定义:dp[i]表示以nums[i]结尾的最长递增子序列长度
        vector<int> dp(nums.size(), 1);
        // 定初值:最长递增子序列的最小长度为1
        int res = 1;
        // 定序:从左往右,先遍历前面的元素
        for(int i = 1; i < nums.size(); i++) {
            for(int j = 0; j < i; j++) {
                // 定式:如果nums[j] < nums[i],则考虑将nums[i]加入到以nums[j]结尾的子序列中
                if(nums[j] < nums[i]) {
                    dp[i] = max(dp[i], dp[j] + 1);
                }
            }
            // 更新最长递增子序列长度
            res = max(res, dp[i]);
        }
        return res;
    }
};

152. 乘积最大子数组

给你一个整数数组 nums ,请你找出数组中乘积最大的非空连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。

测试用例的答案是一个 32-位 整数。

子数组 是数组的连续子序列。

示例 1:

输入: nums = [2,3,-2,4]
输出: 6
解释: 子数组 [2,3] 有最大乘积 6。

示例 2:

输入: nums = [-2,0,-1]
输出: 0
解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。

提示:

  • 1 <= nums.length <= 2 * 104
  • -10 <= nums[i] <= 10
  • nums 的任何前缀或后缀的乘积都 保证 是一个 32-位 整数

维护两个dp数组是因为乘积的最大值可能同时受到正负数的影响。一个dp数组用于保存乘积的最大值,另一个dp数组用于保存乘积的最小值。乘积的最小值通常为负数,当遇到负数时,最小值可能变成最大值。所以需要同时维护两个dp数组来处理这种情况。

class Solution {
public:
    int maxProduct(vector<int>& nums) {
        // 定义
        // dp[i]表示以第i个元素结尾的子数组的乘积的最大值
        // dp_min[i]表示以第i个元素结尾的子数组的乘积的最小值

        // 定式
        // dp[i] = max(nums[i], dp[i-1] * nums[i], dp_min[i-1] * nums[i])
        // dp_min[i] = min(nums[i], dp[i-1] * nums[i], dp_min[i-1] * nums[i])

        // 定初值
        // dp[0] = nums[0]
        // dp_min[0] = nums[0]

        // 定序
        // 从左到右遍历数组

        int n = nums.size();
        if (n == 0) return 0;
        vector<int> dp(n, 0); // dp数组用于保存最大乘积
        vector<int> dp_min(n, 0); // dp_min数组用于保存最小乘积
        dp[0] = nums[0]; // 初始值为第一个元素
        dp_min[0] = nums[0]; // 初始值为第一个元素
        int res = nums[0];
        for (int i = 1; i < n; i++) {
            dp[i] = max(nums[i], max(dp[i-1] * nums[i], dp_min[i-1] * nums[i])); // 更新最大乘积
            dp_min[i] = min(nums[i], min(dp[i-1] * nums[i], dp_min[i-1] * nums[i])); // 更新最小乘积
            res = max(res, dp[i]); // 更新结果
        }
        return res;
    }
};

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背包,结构固定

class Solution {
public:
    // 等价 01 背包
    // 背包最大容量:sum/2
    // 物品 i :nums[i]
    // 物品 i 重量:nums[i]
    // 物品 i 价值:nums[i]
    bool canPartition(vector<int>& nums) {
        // 1维 dp 解 01 背包,套路固定:
        // dp 数组含义:容量为 j 时最大价值
        // 遍历顺序:外物品,内背包,内倒序
        // 1 <= nums.length <= 200
        // 1 <= nums[i] <= 100
        // 和最大为 20000, 故 dp 长度取 20000/2+1,即 10001
        // 0 下标表示容量为 0,此时价值也为 0,故取 0
        // 带覆盖 → 非 0 下标初始值保证取最值正常进行即可,故取 0
        // 故所有下标均初始化为 0
        vector<int> dp(10001, 0);
        int sum = 0;
        for(int i = 0; i < nums.size(); i++){
            sum += nums[i];
        }
        if(sum % 2 == 1) return false; //必不可能由两个整数等分

        int bagMax = sum / 2;
        for(int i = 0; i < nums.size(); i++){
            for(int j =  bagMax; j >= nums[i]; j--){
                dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]);
            }
        }

        if (dp[bagMax] == bagMax) return true;

        return false;
    }
};

32. 最长有效括号

给你一个只包含 '('')' 的字符串,找出最长有效(格式正确且连续)括号子串的长度。

示例 1:

输入:s = "(()"
输出:2
解释:最长有效括号子串是 "()"

示例 2:

输入:s = ")()())"
输出:4
解释:最长有效括号子串是 "()()"

示例 3:

输入:s = ""
输出:0

提示:

  • 0 <= s.length <= 3 * 104
  • s[i]'('')'
class Solution {
public:
    int longestValidParentheses(string s) {
        // 定义:dp[i]表示以索引i结尾的最长有效括号的长度
      	// 定初值:索引为 0 时,最长有效括号长度为 0
        vector<int> dp(s.length(), 0);
        int maxLen = 0;

        // 定序:从左向右遍历字符串
        for (int i = 1; i < s.length(); i++) {
          	//只有在')'字符之前才可能有有效括号
            if (s[i] == ')') {
                // 定式:如果s[i-1]是'(',那么dp[i]=2+dp[i-2],否则dp[i]=2+dp[i-1]+dp[i-dp[i-1]-2]
                if (s[i - 1] == '(') {
                    // 当前字符为')',前一个字符为'(',形成了一对有效括号
                    // 更新dp[i]为dp[i-2]+2
                    dp[i] = (i - 2 >= 0 ? dp[i - 2] : 0) + 2;
                } else if (i - dp[i - 1] - 1 >= 0 && s[i - dp[i - 1] - 1] == '(') {
                  	// 当前字符为')',前一个字符为')'
  									// 如果前一个字符的最长有效括号长度大于0,并且前一个字符的前面一个字符为'('
                  	// 则可以与之匹配,形成更长的有效括号
                    // 更新dp[i]为dp[i-1]+2+dp[i-dp[i-1]-2]
                    dp[i] = dp[i - 1] + 2 + (i - dp[i - 1] - 2 >= 0 ? dp[i - dp[i - 1] - 2] : 0);
                }
                // 更新最大长度
                maxLen = max(maxLen, dp[i]);
            }
        }

        // 返回最长有效括号的长度
        return maxLen;
    }
};

标签:20,速通,nums,int,min,示例,hot,数组,dp
From: https://www.cnblogs.com/ba11ooner/p/17663388.html

相关文章

  • 2023.8.28
    A长为\(n=2^k-1\)的纸条,编号为\([0,n-1)\),将纸条对折\(k\)次(每次将右边翻转至左边下面),记形成的序列为\(\{a_n\}\).\(m\)次询问,给定\(l,r\)求解:\[F(l,r)=a_l+a_{l+1}\oplusa_{l+2}+a_{l+3}\oplusa_{l+4}+\dotsa_r\]若\(l\)为偶数,那么先计算\(+\),否则先计算\(\o......
  • 【OGF、Lucas】P4640 [BJWC2008] 王之财宝
    显然,就是有一些的OGF为\(\frac{1}{1-x}\),有一些为\(\frac{1-x^{b_i+1}}{1-x}\)。乘起来即可。发现不太好算分子,考虑枚举哪些算了。然后我们考虑\(2^t\)的枚举子集。然后直接乘上对应的\(b_i+1\)的系数即可。然后我们要求分母第\(i\)位的系数,这个很典,\(i\)......
  • Python学习日记 2023年8月28日
    importrequestsfromlxmlimportetreeimportreurl='https://image.baidu.com/search/acjson?tn=resultjson_com&logid=8700291432374701138&ipn=rj&ct=201326592&is=&fp=result&fr=ala&word=%E8%A1%A8%E6%83%85%E5%8C%85&query......
  • Harbour.Space Scholarship Contest 2023-2024 (Div. 1 + Div. 2)
    A.给三个数\(x\)\(y\)\(n\)。需要构造一个长度为\(n\)的数组满足以下条件\(a_1=x\),\(a_n=y\)。\(a\)严格递增。定义\(b_i=a_{i+1}-a_{i}\),\(b\)严格递减。显然前两个条件非常宽松,定义好起始点,让\(a\)严格单调递增即可。显然\(b\)是\(a\)的差......
  • RISC-V 中国峰会 | OpenMPL引人注目,RISC-V Summit China 2023圆满落幕
    RISC-V中国峰会圆满落幕     2023年8月25日,为期三天的RISC-V中国峰会(RISC-VSummitChina2023)圆满落幕。本届峰会以“RISC-V生态共建”为主题,结合当下全球新形势,把握全球新时机,呈现RISC-V全球新观点、新趋势。吸引了超过百家企业及研究机构、开源技术社区参与交流,近百家媒......
  • 云原生周刊:CNCF 宣布 KEDA 毕业 | 2023.8.28
    开源项目推荐KDashKDash是一个用Rust构建的简单快速的Kubernetes仪表板。它提供了一个终端界面,用于监视和管理Kubernetes集群。该仪表板具有多种功能,包括节点指标、资源监视、自定义资源定义、容器日志流式传输、上下文切换等。它还支持不同的主题和键盘快捷键操作。fub......
  • 20.LINUX中的read函数
    20.LINUX中的read函数1.read函数的函数原型#include<unistd.h>ssize_tread(intfd,void*buf,size_tcount);函数原型为:ssize_tread(intfd,void*buf,size_tcount);其中,fd为文件描述符;buf表示读出数据缓冲区地址;count表示读出的字节数。返回值:若读取成功,则返回读到的......
  • BUUCTF [强网杯 2019]随便注
    判断传参方式,输入1'or1=1,URL传参,所以是get。报错error1064:YouhaveanerrorinyourSQLsyntax;checkthemanualthatcorrespondstoyourMariaDBserverversionfortherightsyntaxtousenear'''atline1报错说明后端参数后面有可能存在其他sql语句,我们......
  • unbutu20.04离线安装谷歌浏览器
    浏览器安装包下载地址 链接:https://pan.quark.cn/s/634b6bed2f68 下载之后上传到你的unbutu在你存安装包的路径输入dpkg-igoogle-chrome-stable_current_amd64.deb之后按照系统提示跟安装其他软件一样......
  • 20 JavaScript和HTML交互
    20JavaScript和HTML交互在HTML中可以直接在标签上给出一些事件的触发.例如,页面上的一个按钮.<inputtype="button"value="点我"/>我们能够知道此时在页面中会产生一个按钮.但是该按钮无论如何进行点击.都不会触发任何事件.但,此时我要告诉你,人家其实触发了.只是......