【Leetcode】动态规划 刷题训练(八)

这篇具有很好参考价值的文章主要介绍了【Leetcode】动态规划 刷题训练(八)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

413. 等差数列划分

点击查看:等差数列划分


如果一个数列 至少有三个元素 ,并且任意两个相邻元素之差相同,则称该数列为等差数列。
例如,[1,3,5,7,9]、[7,7,7,7] 和 [3,-1,-5,-9] 都是等差数列。
给你一个整数数组 nums ,返回数组 nums 中所有为等差数组的 子数组 个数。
子数组 是数组中的一个连续序列。

示例 1:
输入:nums = [1,2,3,4]
输出:3
解释:nums 中有三个子等差数组:[1, 2, 3]、[2, 3, 4] 和 [1,2,3,4] 自身。
示例 2:
输入:nums = [1]
输出:0


状态转移方程

【Leetcode】动态规划 刷题训练(八),算法刷题,leetcode,动态规划,算法

dp[i]:表示以i位置元素为结尾的所有子数组中等差数列的个数


【Leetcode】动态规划 刷题训练(八),算法刷题,leetcode,动态规划,算法

若ABCD为等差数列,而D与B C也能形成等差数列,ABCDE也是一个等差数列


【Leetcode】动态规划 刷题训练(八),算法刷题,leetcode,动态规划,算法

若想求以i为结尾的所有子数组的等差数列的个数,
而子数组是连续的,想要构成等差数列,至少使i位置与 i-1和i-2位置构成等差数列


dp[i]分为两种情况

情况1:i i-1 i-2位置元素 可以构成等差数列

【Leetcode】动态规划 刷题训练(八),算法刷题,leetcode,动态规划,算法

假设i-2位置元素为a,i-1位置元素为b,i位置元素为c
则三者之间的差值相同,即 c-b==b-a

v以a b 为结尾的等差数列 ,由于c 与a b 也能构成等差数列,所以 以 a b c 为结尾也为等差数列
而以 a b为结尾 就相当于 以 b为结尾 即dp[i-1](以i-1位置为结尾的所有等差数列的个数)
而a b c 属于等差数列 ,且不在dp[i-1]的情况之内 ,所以 需要+1

该情况下: dp[i]=dp[i-1]+1


情况2:i i-1 i-2位置元素 不构成等差数列

【Leetcode】动态规划 刷题训练(八),算法刷题,leetcode,动态规划,算法

假设i-2位置元素为a,i-1位置元素为b,i位置元素为c
则三者之间的差值不同 即 c-b不等于b-a

因为子数组是连续的,而a b c不构成等差数列,前面构不构成等差数列就没有意义了
该情况下: dp[i]=0


状态转移方程为:
dp[i]= c-b==b-a?dp[i-1]+1:0

完整代码

class Solution {
public:
    int numberOfArithmeticSlices(vector<int>& nums) {
         int n=nums.size();
         vector<int>dp(n,0);
         int i=0;
         int sum=0;
         for(i=2;i<n;i++)
         {
             //状态转移方程
             dp[i]=nums[i]-nums[i-1]==nums[i-1]-nums[i-2]?dp[i-1]+1:0;
             sum+=dp[i];
         }
         //返回dp表中所有值之和
         return sum;
    }
};

由于等差数列要求至少有三个元素,当只有一个/两个元素时,不满足要求,所以dp[0]=0 dp[1]=0

978. 最长湍流子数组

点击查看:最长湍流子数组

给定一个整数数组 arr ,返回 arr 的 最大湍流子数组的长度 。
如果比较符号在子数组中的每个相邻元素对之间翻转,则该子数组是 湍流子数组 。
更正式地来说,当 arr 的子数组 A[i], A[i+1], …, A[j] 满足仅满足下列条件时,我们称其为湍流子数组:
若 i <= k < j :
当 k 为奇数时, A[k] > A[k+1],且
当 k 为偶数时,A[k] < A[k+1];
或 若 i <= k < j :
当 k 为偶数时,A[k] > A[k+1] ,且
当 k 为奇数时, A[k] < A[k+1]。

示例 1:
输入:arr = [9,4,2,10,7,8,8,1,9]
输出:5
解释:arr[1] > arr[2] < arr[3] > arr[4] < arr[5]
示例 2:
输入:arr = [4,8,12,16]
输出:2


题目解析

【Leetcode】动态规划 刷题训练(八),算法刷题,leetcode,动态规划,算法

B的值比A大,则呈现上升趋势
C的值比B小,则呈现下降趋势
D的值比C大,则呈现上升趋势
则ABCD数组为湍流子数组

状态转移方程

【Leetcode】动态规划 刷题训练(八),算法刷题,leetcode,动态规划,算法

dp[i]:表示 以i位置为结尾的所有子数组中,最长的湍流数组的长度

刚开始分析写出dp[i],但是会发现湍流数组有上升和下降趋势的问题,而dp[i]无法解决,所以再次定义f[i]和g[i]


【Leetcode】动态规划 刷题训练(八),算法刷题,leetcode,动态规划,算法

f[i]:表示以i位置为结尾的所有子数组中,最后呈现上升趋势的最长湍流数组的长度


【Leetcode】动态规划 刷题训练(八),算法刷题,leetcode,动态规划,算法

g[i]:表示以i位置为结尾的所有子数组中,最后呈现下降趋势的最长湍流数组的长度


f[i]状态转移方程

【Leetcode】动态规划 刷题训练(八),算法刷题,leetcode,动态规划,算法

假设i-1位置的元素的值为a,i位置的元素值为b


情况1 a>b

【Leetcode】动态规划 刷题训练(八),算法刷题,leetcode,动态规划,算法

与前面数组结合 只能呈现下降趋势
若想自己呈现上升趋势,单独1个构成子数组,最后一个位置既可以上升,也可以下降
即 f[i]=1


情况2 a<b

【Leetcode】动态规划 刷题训练(八),算法刷题,leetcode,动态规划,算法

此时呈现上升趋势,符合f[i]的含义

【Leetcode】动态规划 刷题训练(八),算法刷题,leetcode,动态规划,算法

再次寻找以i-1位置为结尾,最后呈现下降趋势的湍流数组的最长的长度 即g[i-1]
再加上由a到b的长度 即+1
该情况下: f[i]=g[i-1]+1


情况3 a==b

【Leetcode】动态规划 刷题训练(八),算法刷题,leetcode,动态规划,算法

在该情况下想要使i位置处呈现上升趋势,只能单独1个构成子数组
即 f[i]=1

g[i]状态转移方程

【Leetcode】动态规划 刷题训练(八),算法刷题,leetcode,动态规划,算法

假设i-1位置的元素的值为a,i位置的元素值为b


情况1 a>b

【Leetcode】动态规划 刷题训练(八),算法刷题,leetcode,动态规划,算法

此时正好呈现下降趋势, 符合g[i]含义

【Leetcode】动态规划 刷题训练(八),算法刷题,leetcode,动态规划,算法

再次寻找以i-1位置为结尾,最后呈现上升趋势的湍流数组的最长的长度 即f[i-1]
再加上由a到b的长度 即+1

该情况下:g[i]=f[i-1]+1


情况2 a<b

【Leetcode】动态规划 刷题训练(八),算法刷题,leetcode,动态规划,算法

在该情况下想要使i位置处呈现下降趋势,只能单独1个构成子数组
即g[i]=1


情况3 a==b

【Leetcode】动态规划 刷题训练(八),算法刷题,leetcode,动态规划,算法

在该情况下想要使i位置处呈现下降趋势,只能单独1个构成子数组
即g[i]=1

完整代码

class Solution {
public:
    int maxTurbulenceSize(vector<int>& nums) {
       int n=nums.size();
       //f g表 都表示湍流数组的最长长度
       //而单独一个数本身,表示最低长度为1
       //所以f/g 最差长度也为1
       vector<int>f(n,1);
       vector<int>g(n,1);

       int i=0;
       //单独一个数 返回1 ,所以初始值为1
       int fmax=1;
       int gmax=1;
       for(i=1;i<n;i++)
       {
           //f[i] a<b情况
           if(nums[i-1]<nums[i])
           {
               f[i]=g[i-1]+1;
           }
           //g[i] a>b情况
           else if(nums[i-1]>nums[i])
           {
               g[i]=f[i-1]+1;
           }
           fmax=max(fmax,f[i]);
           gmax=max(gmax,g[i]);
       }
       //返回 f和g表中的最大值
       return max(fmax,gmax);
    }
};

单独一个数本身,可以构成上升或者下降趋势 ,所以湍流数组 长度最差也为1
所以可以把f/g表中里面的元素全部初始化为1

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

状态转移方程

dp[i]:表示 [0,i]区间内的字符串,能否被字典中的单词拼接而成
若能够拼接而成,则返回true ,若不能则返回false

根据最后一个位置来划分问题


【Leetcode】动态规划 刷题训练(八),算法刷题,leetcode,动态规划,算法

若能确定前面这个部分能够拼接成功,并且保证 最后一个单词在字典中,整体字符串就能被拼接而成

设j作为最后一个单词的起始位置的下标
j的范围为 0<=j<=i
0表示整个字符串作为最后一个单词
i表示最后一个字符作为最后一个单词


【Leetcode】动态规划 刷题训练(八),算法刷题,leetcode,动态规划,算法

字符串的起始位置为0
j作为最后一个单词的起始位置,所以字符串的终止位置为j-1

[0,j-1]区间内的字符串 需要判断是否能被字典中的单词拼接而成 即dp[j-1]
最后一个单词的范围是 [j,i] ,这段区间内的子串是否在字典中


状态转移方程为:
当dp[i-1] 为true 并且 最后一个单词([j-i]范围内)在字典中 两者都满足 ,结果才为true
若有任意一个不成立,则为false

初始化

当j为0时,会发生越界问题

【Leetcode】动态规划 刷题训练(八),算法刷题,leetcode,动态规划,算法

为了防止这种越界问题出现,所以加入一个虚拟节点
扩展后的数组,虚拟节点处下标为0,则 原数组的元素下标从1开始


若j为0,表示把0到i这个区间整个看作是最后一个单词,若最后一个单词在字典中,要返回true,
dp[0]=true
这样才能保证两者都为true


假设原始字符串为s ,辅助位置一般是空格
s=’ ’ +s
原始字符串加上辅助位置后,原始字符串相当于从1开始计数,正好与新的dp表对应
文章来源地址https://www.toymoban.com/news/detail-516638.html

完整代码

class Solution {
public:
    bool wordBreak(string s, vector<string>& wordDict) {
        unordered_set<string>hash;
        for(auto& s:wordDict)
        {
           hash.insert(s);
        }
         int n=s.size();
         //为了防止越界问题,所以多加一个虚拟节点
         vector<bool>dp(n+1);
         //初始化
         dp[0]=true;
         s=' '+s;//使原始字符串的下标统一+1
         int i=0;
         int j=0;
         for(i=1;i<=n;i++)
         {
             for(j=i;j>=1;j--)
             {
                 //在hash中判断 s中对应的子串在不在 若在返回1 不在返回0
                 if(  dp[j-1]&&  hash.count(s.substr(j,i-j+1)) )
                 {
                     dp[i]=true;
                     break;//找到一种情况即可
                 }
             }
         }
         //因为多加了个虚拟节点,所以下标+1
         return dp[n];
    }
};

到了这里,关于【Leetcode】动态规划 刷题训练(八)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【LeetCode】动态规划 刷题训练(二)

    点击查看:不同路径 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。 问总共有多少条不同的路径? 示例 1: 输入:m = 3, n = 7 输出:28 示例

    2024年02月10日
    浏览(23)
  • 【LeetCode】 动态规划 刷题训练(三)

    点击查看:下降路径最小和 给你一个 n x n 的 方形 整数数组 matrix ,请你找出并返回通过 matrix 的下降路径 的 最小和 。 下降路径 可以从第一行中的任何元素开始,并从每一行中选择一个元素。在下一行选择的元素和当前行所选元素最多相隔一列(即位于正下方或者沿对角线

    2024年02月10日
    浏览(28)
  • 【LeetCode】动态规划 刷题训练(五)

    点击查看:粉刷房子 假如有一排房子,共 n 个,每个房子可以被粉刷成红色、蓝色或者绿色这三种颜色中的一种,你需要粉刷所有的房子并且使其相邻的两个房子颜色不能相同。 当然,因为市场上不同颜色油漆的价格不同,所以房子粉刷成不同颜色的花费成本也是不同的。

    2024年02月11日
    浏览(32)
  • 【leetcode刷题之路】剑指Offer(4)——分治+排序算法+动态规划

    8 分治算法 8.1 【递归】剑指 Offer 07 - 重建二叉树 https://leetcode.cn/problems/zhong-jian-er-cha-shu-lcof/   前序遍历是根左右,中序遍历是左根右,这也就意味着前序遍历的第一个节点是整棵树的根节点,顺着这个节点找到它在中序遍历中的位置,即为in_root,那么in_root左边的都在左子

    2024年02月11日
    浏览(43)
  • 【leetcode刷题之路】初级算法(2)——链表+树+排序和搜索+动态规划

    3.1 【链表】删除链表中的节点 https://leetcode.cn/problems/delete-node-in-a-linked-list/ 给出的就是要删除的那个节点,直接前后移动就行了。 3.2 【双指针】删除链表的倒数第 N 个结点 https://leetcode.cn/problems/remove-nth-node-from-end-of-list/ 利用双指针left和right,首先让right遍历n个节点,再让两

    2024年02月10日
    浏览(38)
  • 算法训练day41|动态规划 part03(LeetCode343. 整数拆分、96.不同的二叉搜索树)

    题目链接🔥🔥 给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。 返回你可以获得的最大乘积。 示例 1: 输入: 2 输出: 1 解释: 2 = 1 + 1, 1 × 1 = 1。 示例 2: 输入: 10 输出: 36 解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。 说明: 你可以假设 n 不小于 2 且不大于

    2024年02月10日
    浏览(32)
  • Leetcode 刷题 动态规划

    309. 最佳买卖股票时机含冷冻期 1. 确定dp数组以及下标的含义 具体可以区分出如下四个状态: 状态一:持有股票状态(今天买入股票,或者是之前就买入了股票然后没有操作,一直持有) 不持有股票状态,这里就有两种卖出股票状态 状态二:保持卖出股票的状态(两天前就

    2024年02月11日
    浏览(32)
  • 【leetcode刷题之路】面试经典150题(8)——位运算+数学+一维动态规划+多维动态规划

    20 位运算 20.1 【位运算】二进制求和 题目地址:https://leetcode.cn/problems/add-binary/description/?envType=study-plan-v2envId=top-interview-150   按位逆序运算。 20.2 【位运算】颠倒二进制位 题目地址:https://leetcode.cn/problems/reverse-bits/description/?envType=study-plan-v2envId=top-interview-150   详见代码

    2024年04月16日
    浏览(61)
  • 【leetcode 力扣刷题】回文串相关题目(KMP、动态规划)

    题目链接:5. 最长回文子串 题目内容: 题目就是要我们找s中的回文子串,还要是最长的。其实想想,暴力求解也行……就是遍历所有的子串,同时判断是不是回文串,是的话再和记录的最大长度maxlen比较,如果更长就更新。时间复杂度直接变成O(n^3)。 优化的点在于,假设子

    2024年02月09日
    浏览(34)
  • LeetCode刷题笔记【30】:动态规划专题-2(不同路径、不同路径 II)

    参考前文 参考文章: LeetCode刷题笔记【29】:动态规划专题-1(斐波那契数、爬楼梯、使用最小花费爬楼梯) LeetCode链接:https://leetcode.cn/problems/unique-paths/description/ 动态规划 : 创建m×n的数组, 对应这个地图, 数组 val 表示 有几种方法可以走到这一格 最开始, 第一行和第一列v

    2024年02月09日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包