Reputation: 2153
In the given array, I am trying to find the total number of subsequences such that:
For example, in an array: [10,13,7,8,14,200, 876, 11]
, it has 5 subsequences which follow the above condition.
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.
How can I approach this? I have an intuition that the approach could be similar to Longest Increasing Subsequence, but not sure how.
Upvotes: 1
Views: 2210
Reputation: 496
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
.
But if an optimal solution is required I would suggest an O(N*log2(N))
solution, where finding the sum in the range [x-k,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.
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.
In this approach you don't need to worry about K
even if it was too big.
Upvotes: 0
Reputation: 8101
@VFX has already proposed a O(N^2)
solution, but in most cases an optimised algorithm would be preferred. So here's a O(K*N)
solution.
Let's say your first element in the subsequence is x
. The next element has to be in the range [x-k, 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.
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]]
Upvotes: 1
Reputation: 496
Let f(i) be the number of subsequences that fulfill the following conditions:
Then the answer to your problem will be f(A.length()-1).
Here is the code in C++ in a bottom-up approach:
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:
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(0);
Upvotes: 2