Javascript 查找连续差为k的数组中的子序列总数

Javascript 查找连续差为k的数组中的子序列总数,javascript,arrays,algorithm,dynamic-programming,subsequence,Javascript,Arrays,Algorithm,Dynamic Programming,Subsequence,在给定数组中,我试图找到子序列的总数,以便: 连续任期之间的差异不大于3个月 子序列的第一个元素是数组的第一个元素 子序列的最后一个元素是数组的最后一个元素 例如,在一个数组中:[10,13,7,8,14200876,11],它有5个子序列遵循上述条件 我正在尝试一种自下而上的方法。我尝试了以下方法,但它没有给出所有子序列和输出4,而不是5 我怎样才能做到这一点?我有一种直觉,即该方法可能类似于最长递增子序列,但不确定如何进行。设f(I)为满足以下条件的子序列数: 以[0]开头 以[i]结

在给定数组中,我试图找到子序列的总数,以便:

  • 连续任期之间的差异不大于3个月
  • 子序列的第一个元素是数组的第一个元素
  • 子序列的最后一个元素是数组的最后一个元素
例如,在一个数组中:
[10,13,7,8,14200876,11]
,它有5个子序列遵循上述条件

我正在尝试一种自下而上的方法。我尝试了以下方法,但它没有给出所有子序列和输出4,而不是5

我怎样才能做到这一点?我有一种直觉,即该方法可能类似于最长递增子序列,但不确定如何进行。

设f(I)为满足以下条件的子序列数:

  • 以[0]开头
  • 以[i]结尾
  • 连续项之间的差值不大于3
那么问题的答案将是f(A.length()-1)

这里是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
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;
}

设f(i)为满足以下条件的子序列数:

  • 以[0]开头
  • 以[i]结尾
  • 连续项之间的差值不大于3
那么问题的答案将是f(A.length()-1)

这里是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
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;
}


@VFX已经提出了一个
O(N^2)
解决方案,但在大多数情况下,优化算法将是首选。所以这里有一个
O(K*N)
解决方案。
假设子序列中的第一个元素是
x
。下一个元素必须在
[x-k,x+k]
范围内。如果知道该范围内所有值的有效序列数,也可以在
O(K)
中找到当前元素的答案。
更正式地说,算法是:

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]]

@VFX已经提出了一个
O(N^2)
解决方案,但在大多数情况下,优化算法将是首选。所以这里有一个
O(K*N)
解决方案。
假设子序列中的第一个元素是
x
。下一个元素必须在
[x-k,x+k]
范围内。如果知道该范围内所有值的有效序列数,也可以在
O(K)
中找到当前元素的答案。
更正式地说,算法是:

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]]

我刚刚注意到@Abhinav的答案是将解决方案优化为
O(K*N)
,而不是
O(N^2)
,这对于小型
K

但如果需要最佳解决方案,我建议使用
O(N*log2(N))
解决方案,在
[x-k,x+k]
范围内求和可以 可以在log2(N)中使用或在其中使用范围和查询(RSQ)作为这两个数据结构提供的标准操作来完成。

如果初始数组中的值较大(如long或double),则可以借助映射完成数据压缩。

在这种方法中,你不需要担心
K
,即使它太大。

我刚刚注意到@Abhinav的答案是优化
O(K*N)
的解决方案,而不是
O(N^2)
,这对小
K
很有效
但如果需要最佳解决方案,我建议使用
O(N*log2(N))
解决方案,在
[x-k,x+k]
范围内求和可以 可以在log2(N)中使用或在其中使用范围和查询(RSQ)作为这两个数据结构提供的标准操作来完成。

如果初始数组中的值较大(如long或double),则可以借助映射完成数据压缩。


在这种方法中,您不需要担心
K
,即使它太大。

您能提供您的代码提供的4个序列吗?@VFX updated。。它会打印除
[10,13,11]
之外的所有内容。您只对满足条件的序列数量感兴趣,对吗?您不需要打印实际的sequences@VFX不……。@VFX您是否也认为这是LIS(最长递增子序列)问题的一种变体?您能否提供您的代码给出的4个序列?@VFX已更新。。它会打印除
[10,13,11]
之外的所有内容。您只对满足条件的序列数量感兴趣,对吗?您不需要打印实际的sequences@VFX不……。@VFX您是否也认为这是LIS(最长递增子序列)问题的一种变体?。我实际上对这个问题理解不够,所以我不确定输出是否正确。所以,我希望我没有在某个地方犯错误。好的,我会检查你的代码,我的代码正确地打印了5,你可以在这里运行它,啊,好的-然后这会产生相同的输出。有一个小问题-我让它无意中打印了整个阵列。如果您不理解逻辑,我可以解释更多细节,请让我知道
f[I]=0初始化
是一个正常的零初始化,而不是一个基本情况,就像您用零初始化计数器一样,因为
f[I]+=f[j]
就像一个计数器,我们需要从零开始。另一方面,基本情况是计算较大情况所需的值。我实际上对这个问题理解不够,所以我不确定输出是否正确。所以,我希望我没有在某个地方犯错误。好的,我会检查你的代码,我的代码正确地打印了5,你可以在这里运行它,啊,好的-然后这会产生相同的输出。有一个小问题-我让它无意中打印了整个阵列。如果您不理解逻辑,我可以解释更多细节,请让我知道
f[I]=0初始化
是一个正常的零初始化,而不是一个基本情况,就像您用零初始化计数器一样,因为
f[I]+=f[j]
就像一个计数器,我们需要从零开始。上