力扣题解( 等差数列划分 II - 子序列)

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

给你一个整数数组 nums ,返回 nums 中所有 等差子序列 的数目。

如果一个序列中 至少有三个元素 ,并且任意两个相邻元素之差相同,则称该序列为等差序列。

  • 例如,[1, 3, 5, 7, 9][7, 7, 7, 7][3, -1, -5, -9] 都是等差序列。
  • 再例如,[1, 1, 2, 5, 7] 不是等差序列。

数组中的子序列是从数组中删除一些元素(也可能不删除)得到的一个序列。

  • 例如,[2,5,10][1,2,1,2 ,4,1,5 ,10] 的一个子序列。

题目数据保证答案是一个 32-bit 整数。

思路:

首先,本道题要求的是所有可能的子序列的数目,要注意此时子序列可以重复出现,因为是友不同位置的同一元素构成的,比如:{5,5,10,15},可以构成两个子序列{5,10,15},{5,10,15},不同点在于用的5来自不同下标。

再者,对于所求的数量与前面所求数量有所关联的题,往往会出现dpi=dpj+1,这里的加一是指会额外多出一种可能,dpj表示在原本所有j位置构成的字串加上i位置仍是字串,因此数量不变。

对于本题,由于在找前面符合条件的字串时,涉及到了前面字串的具体构成(因为构成字串最少需要三个元素),因此需要用多维数组表示。dpij表示i位置数据在前,j位置数据在后,在加上i之前的元素构成子序列,符合条件的数值是2*numi-numj(因为是等差数列)。然后,由于可以出现重复的子序列,因此对于i位置之前所有符合数值的下标都需要进行加上。

复制代码
class Solution {
public:
    int numberOfArithmeticSlices(vector<int>& nums) {
     int n=nums.size();
     vector<vector<int>>dp(n,vector<int>(n));
     unordered_map<long long,vector<int>>hash;
     int sum=0;
     for(int i=0;i<n;i++)
     {
        for(int j=i+1;j<n;j++)
        {  
            long long a=(long long)2*nums[i]-nums[j];
           if(hash.count(a))
           {
              for(auto k:hash[a])
              if(k<i)
              {
                dp[i][j]+=dp[k][i]+1;
            
              }
           }
           sum+=dp[i][j];
    
        }
        hash[nums[i]].push_back(i);
        
     }

     return sum;



    }
};
相关推荐
To_OC6 小时前
LC 49 字母异位词分组:想到哈希表很简单,选对 key 才是精髓
javascript·算法·leetcode
用户9385156350711 小时前
从 O(n²) 到 O(nlogn):一文读懂快速排序的“快”与“妙”
javascript·算法
To_OC12 小时前
手写快排次次翻车?别死背快排模板了,这才是面试官想听的底层逻辑
javascript·算法·排序算法
饼干哥哥12 小时前
Reddit VOC调研太慢?搭一个AI专家团队半小时洞察任何品类|以猫用饮水机为例
人工智能·算法·ai编程
地平线开发者14 小时前
Transformer模型部署之性能优化指南
算法
地平线开发者14 小时前
人在途中:从“编译失败”到“模型可落地”——CUDA 自定义算子
算法·自动驾驶
半个落月17 小时前
从递归到快速排序:用 JavaScript 把分治思想讲明白
javascript·算法·面试
小月土星18 小时前
JavaScript 快速排序:从 pivot、双指针到分治思想
javascript·算法·面试
小月土星18 小时前
JavaScript 递归入门:从 1 到 n 求和,再到数组扁平化
javascript·算法·面试