【LeetCode】446. 等差数列划分II -- 子序列

这篇具有很好参考价值的文章主要介绍了【LeetCode】446. 等差数列划分II -- 子序列。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

题目链接

1. 思路讲解

我们要知道以某个位置为结尾的子序列的数量,可以通过它的以上一位置的为结尾的子序列的数量得知,也就是说,这是一个dp问题。

1.1 dp表的创建

dp问题我们需要创建dp表,如果我们单纯使用dp[i]来表示以 i 位置为结尾的子序列的数量是完全不够的。因为我们不知道以 i-1 位置为结尾的等差数列是怎样的,它的公差是几我们是不知道的。也就是说,我们不确定 i 位置的元素是否能跟到以 i - 1 位置为结尾的数列的后面。

但是,如果知道了数列的后两个元素,也就是知道了 i - 1 位置以及数列中上一个位置的元素,就能知道数列的公差了,也就能知道 i 位置的元素是否能跟到后面了,所以我们需要用两个元素来表示每个dp位置。

创建二维dp表,dp[i][j]表示以 i 位置的元素为数列倒数第二个元素,以 j 位置的元素为数列倒数第一个元素,为结尾的数列数量有多少。(我们人为规定i < j)

1.2 状态转移方程

nums[j] - nums[i]可以得到公差,再由 num[i] - 公差 可以得到上一项的值,记为 a,我们需要知道这个 a 值在nums中是否存在且是否在 i 位置的前面,两个条件都满足才符合题意。

记 a 在nums中的下标为k(至于怎么找到这个k下面会说),我们要找到以 i 和 j 位置为结尾的等差数列的个数,其实找到所有 k 和 i 位置元素结尾的等差数列的个数相加即可(a元素在nums中的位置不只一个,那么k可能就不只一个)。并且也需额外加上一个数列,就是 k,i ,j,本身所构成的等差数列。

那么状态转移方程就为:dp[i][j] += dp[k][i] + 1

1.3 使用哈希表找到k

我们写代码的时候,遍历所有 i 和 j 的组合,时间复杂度就已经到达 N^2 了,如果此时再在数组中去寻找 k ,那么时间复杂度就 N^3了,这大概率是会超时的。

我们可以在dp之前,使用哈希表去将<所有元素,数组下标>绑定在一起,放在哈希表中,这样我们得到了 a 之后,就可以使用哈希表很快地查找到 k 了。

1.4 初始化

刚开始,以 i,j 位置为结尾,只有两个元素,不符合题目中的等差数列,可以记为 0 ,所以我们初始化的时候将dp表中所有的值初始化为 0 即可。又因为,vector会默认初始化为0,所以我们不用手动初始化了。

1.5 返回值

我们要求的是所有的等差数列,所以我们要将所有符合题意的dp[i][j]都加起来然后返回。

1.6 该题坑爹的一点

虽然题目已经说了,返回值以及各个元素的值都在int范围内,但是我们求a的时候,a的值可能会超出int的范围从而出错,所以我们将a的类型要设置为long long。然后用a查找k用的是hash,所以hash的第一个类型也要为long long。

2. 代码编写

【LeetCode】446. 等差数列划分II -- 子序列,题,leetcode,算法,职场和发展文章来源地址https://www.toymoban.com/news/detail-622428.html

class Solution {
public:
    int numberOfArithmeticSlices(vector<int>& nums) {
        int n = nums.size();
        // 创建哈希表,便于很快地找到k
        // 因为k不只一个,所以用vector来存储
        unordered_map<long long, vector<int>> hash;
        for (int i = 0; i < n; i++) hash[nums[i]].push_back(i);

        // 创建二维dp表,第一维为数列的倒数第二个元素,第二维为数列的倒数第一个元素
        vector<vector<int>> dp(n, vector<int>(n));
        
        int ret = 0; // 所有数组的数量

        // i为nums第0个位置时,不管j为几,dp[0][j]都为0,因为只有两个元素
        // 所以从第1个位置开始填表即可,且i一定不为nums最后一个元素
        for (int i = 1; i < n - 1; ++i)
        {
            // j从i+1开始,一直到最后一个位置,寻找符合题意的情况
            for (int j = i + 1; j < n; ++j)
            {
                long long a = (long long)2*nums[i] - nums[j];
                if (hash.count(a)) // 看a是否存在于hash中
                {
                    // 如果存在,遍历a对应的vector
                    for (auto k : hash[a])
                    {
                        // k需要小于i
                        if (k < i) dp[i][j] += dp[k][i] + 1;
                    }
                } 
                ret += dp[i][j];
            }
        }
        return ret;
    }
};

到了这里,关于【LeetCode】446. 等差数列划分II -- 子序列的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 【C语言蓝桥杯每日一题】——等差数列

        😎博客昵称:博客小梦 😊最喜欢的座右铭:全神贯注的上吧!!! 😊作者简介:一名热爱C/C++,算法等技术、喜爱运动、热爱K歌、敢于追梦的小博主! 😘博主小留言:哈喽! 😄各位CSDN的uu们,我是你的博客好友小梦,希望我的文章可以给您带来一定的帮助,话不

    2023年04月09日
    浏览(80)
  • 华为OD机试真题 Java 实现【等差数列】【2023 B卷 100分】,附详细解题思路

    本专栏收录于《华为OD机试(JAVA)真题(A卷+B卷)》。 刷的越多,抽中的概率越大 ,每一题都有详细的答题思路、详细的代码注释、样例测试,订阅后,专栏内的文章都可看,可加入华为OD刷题群(私信即可),发现新题目,随时更新,全天CSDN在线答疑。 专栏福利 :限时订

    2024年02月16日
    浏览(63)
  • 蓝桥杯专题-真题版含答案-【九宫幻方】【打鱼还是晒网】【阶乘尾数零的个数】【等差素数列】

    点击跳转专栏=Unity3D特效百例 点击跳转专栏=案例项目实战源码 点击跳转专栏=游戏脚本-辅助自动化 点击跳转专栏=Android控件全解手册 点击跳转专栏=Scratch编程案例 点击跳转=软考全系列 点击跳转=蓝桥系列 专注于 Android/Unity 和各种游戏开发技巧,以及 各种资源分享 (网站、

    2024年02月15日
    浏览(43)
  • LeetCode 38. 外观数列

    给定一个正整数 n ,输出外观数列的第 n 项。 「外观数列」是一个整数序列,从数字 1 开始,序列中的每一项都是对前一项的描述。 你可以将其视作是由递归公式定义的数字字符串序列: countAndSay(1) = “1” countAndSay(n) 是对 countAndSay(n-1) 的描述,然后转换成另一个数字字符串

    2024年01月18日
    浏览(32)
  • LeetCode 38 外观数列

    外观数列 给定一个正整数 n ,输出外观数列的第 n 项。 「外观数列」是一个整数序列,从数字 1 开始,序列中的每一项都是对前一项的描述。 你可以将其视作是由递归公式定义的数字字符串序列: countAndSay(1) = \\\"1\\\" countAndSay(n) 是对 countAndSay(n-1) 的描述,然后转换成另一个数字

    2024年02月02日
    浏览(38)
  • Leetcode38. 外观数列

    给定一个正整数 n ,输出外观数列的第 n 项。 「外观数列」是一个整数序列,从数字 1 开始,序列中的每一项都是对前一项的描述。 你可以将其视作是由递归公式定义的数字字符串序列: countAndSay(1) = “1” countAndSay(n) 是对 countAndSay(n-1) 的描述,然后转换成另一个数字字符串

    2023年04月26日
    浏览(54)
  • LeetCode 面试题 16.17. 连续数列

      给定一个整数数组,找出总和最大的连续数列,并返回总和。 示例: 输入: [-2,1,-3,4,-1,2,1,-5,4] 输出: 6 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。 进阶: 如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。   点击此处跳转题目。   使用动态

    2024年02月05日
    浏览(36)
  • LeetCode刷题---斐波那契数列模型

    顾得泉: 个人主页 个人专栏: 《Linux操作系统》  《C/C++》  《LeedCode刷题》 键盘敲烂,年薪百万! 题目链接:1137. 第 N 个泰波那契数   泰波那契序列Tn定义如下:         T0=0,T1=1,T2= 1,且在n=0的条件下Tn+3= Tn+Tn+1t+Tn+2         给你整数n,请返回第n个泰波那契数Tn的值

    2024年02月04日
    浏览(53)
  • Golang | Leetcode Golang题解之第38题外观数列

    题目: 题解:

    2024年04月25日
    浏览(65)
  • 代码随想录 Leetcode763. 划分字母区间

    2024年02月21日
    浏览(121)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包