简体   繁体   English

查找具有连续差 = k 的数组中的子序列总数

[英]Finding total number of subsequences in an array with consecutive difference = k

In the given array, I am trying to find the total number of subsequences such that:在给定的数组中,我试图找到子序列的总数,例如:

  • the difference between the consecutive terms is not greater than 3连续词之间的差不大于3
  • the first element of the subsequence is the first element of the array子序列的第一个元素是数组的第一个元素
  • the last element of the subsequence is the last element of the array子序列的最后一个元素是数组的最后一个元素

For example, in an array: [10,13,7,8,14,200, 876, 11] , it has 5 subsequences which follow the above condition.例如,在一个数组中: [10,13,7,8,14,200, 876, 11] ,它有 5 个子序列遵循上述条件。

I am trying a bottom-up approach to this.我正在尝试一种自下而上的方法。 I tried the following, but it does not give all the subsequences and outputs 4 instead of 5.我尝试了以下方法,但它没有给出所有子序列并输出 4 而不是 5。

How can I approach this?我该如何处理? I have an intuition that the approach could be similar to Longest Increasing Subsequence, but not sure how.我有一种直觉,该方法可能类似于最长递增子序列,但不确定如何。

Let f(i) be the number of subsequences that fulfill the following conditions:令 f(i) 为满足以下条件的子序列数:

  • Start by A[0]从 A[0] 开始
  • End by A[i]以 A[i] 结束
  • The difference between the consecutive terms is not greater than 3连续词之间的差异不大于3

Then the answer to your problem will be f(A.length()-1).那么问题的答案将是 f(A.length()-1)。

Here is the code in C++ in a bottom-up approach:这是 C++ 中的代码,采用自下而上的方法:

int A[] = {10,13,7,8,14,11};
int f[6];
int n = 6;
    
for (int i=0;i<n;i++) f[i] = 0;
f[0]=1;
for (int i=1;i<n;i++){
  for (int j=0;j<i;j++){
     if (abss(A[i] - A[j]) <= 3)
         f[i] += f[j];
  }
}
cout<<f[n-1]<<endl;//printing the result

Here is the code written in C++ in top-down approach:这是用 C++ 自上而下的方法编写的代码:

int A[] = {10,13,7,8,14,11};
int n = 6;

int memo[6];//initialized with -1s;

int count(int currIndex){
  if (currIndex == n-1) return 1;
  if (memo[currIndex] != -1) return memo[currIndex];
  
  int res = 0;
  for (int i=currIndex+1 ; i<n ; i++){
      if (abss(A[currIndex] - A[i]) <= 3){
            res += count(i);
      }
  }
    
  memo[currIndex] = res;
  return res;
}

And the result will be by calling count at first index like this:结果将是在第一个索引处调用 count ,如下所示:

count(0);

@VFX has already proposed a O(N^2) solution, but in most cases an optimised algorithm would be preferred. @VFX 已经提出了一个O(N^2)的解决方案,但在大多数情况下,优化算法是首选。 So here's a O(K*N) solution.所以这是一个O(K*N)的解决方案。
Let's say your first element in the subsequence is x .假设您在子序列中的第一个元素是x The next element has to be in the range [xk, x+k] .下一个元素必须在[xk, x+k]范围内。 If you know the number of valid sequences for all values in that range, you can find the answer for the current element in O(K) as well.如果您知道该范围内所有值的有效序列数,您也可以在O(K)中找到当前元素的答案。
More formally, the algorithm would be:更正式地说,该算法将是:

arr = []              // your list
counter = {}          // a dictionary or hashmap to keep count of sequences
counter[arr[-1]] = 1
for i in range (len(arr)-2 to 0):
    curr_element = a[i]
    sequences = 0
    for x in range (curr_element-k to curr_element+k):
        sequences += counter[x]
    counter[curr_element] += sequences

final_answer = counter[arr[0]]

I have just noticed @Abhinav's answer to optimize the solution to O(K*N) instead of O(N^2) which will work fine for a small K .我刚刚注意到@Abhinav 的答案是优化O(K*N)而不是O(N^2)的解决方案,这适用于小K
But if an optimal solution is required I would suggest an O(N*log2(N)) solution, where finding the sum in the range [xk,x+k] can be done in log2(N) using Segment Tree or Binary Indexed Tree(Fenwick Tree) where Range Sum Query(RSQ) is a standard operation that these 2 data structures provide.但是如果需要最佳解决方案,我建议使用O(N*log2(N))解决方案,其中可以使用段树二进制索引在 log2(N) 中找到范围[xk,x+k]中的总和树(Fenwick Tree) ,其中范围求和查询(RSQ)是这两种数据结构提供的标准操作。

In case the values inside the initial array are big(like long or double), a data compression can be done with the help of a Map.如果初始数组中的值很大(如 long 或 double),则可以在 Map 的帮助下完成数据压缩。
In this approach you don't need to worry about K even if it was too big.在这种方法中,即使K太大,您也不必担心它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM