![]() |
VOOZH | about |
Given an array arr[] of n positive integers. The task is to count the number of Arithmetic Progression subsequences in the array.
Note: Empty sequence or single element sequence is Arithmetic Progression.
Examples:
Input: arr[] = [1, 2, 3]
Output: 8
Explanation: Arithmetic Progression subsequence from the given array are: [], [1], [2], [3], [1, 2],
[2, 3], [1, 3], [1, 2, 3].Input: arr[] = [10, 20]
Output: 4
Explanation: Arithmetic Progression subsequence from the given array are: [], [10], [20], [10, 20].
Table of Content
For the recursive approach, the problem involves counting arithmetic subsequences with a certain difference. At each step, the number of available elements decreases by 1. Consider the current element as part of the arithmetic subsequence. In this case, the difference between the current element and the previous element is passed to the recursive call. Alternatively, skip the current element, and the sequence continues without including it.
Base case:
- if idx == n, return 1 (meaning all elements have been processed)
Mathematically, the recurrence relation looks like this:
numberOfAP(arr, n, idx, pre, count, diff) = numberOfAP(arr, n, idx + 1, idx, count + 1, arr[idx] - arr[pre]) OR
numberOfAP(arr, n, idx + 1, pre, count, diff)
8
1. Optimal Substructure:
The solution to count all arithmetic subsequences can be constructed from optimal solutions to subproblems.
- If pre != -1 and diff == INT_MIN, we are setting the difference between the current element and the previous element. Once this difference is established, we continue checking if the current element extends the arithmetic progression.
- If pre == -1, this means we are at the beginning of the subsequence, and we can freely start the subsequence with the current element.
- If diff == arr[idx] - arr[pre], then the current element fits into the existing arithmetic progression, so we continue the progression by including the current element.
2. Overlapping Subproblems:
Recursive calls for counting AP subsequences involve recalculating the same state multiple times. To avoid recomputation, we use memoization with a unique key for each state. This approach reduces redundant calculations by storing results in memo. For instance, numberOfAP reuses previously computed results whenever it encounters the same key.
The memoization key for each state is:
- key = to_string(idx) + "_" + to_string(pre) + "_" + to_string(count) + "_" + to_string(diff)
The memoization relation then becomes:
memo[key] = numberOfAP(arr, n, idx + 1, idx, count + 1, arr[idx] - arr[pre], memo
+ numberOfAP(arr, n, idx + 1, idx, count + 1, diff, memo) +
+ numberOfAP(arr, n, idx + 1, pre, count, diff, memo)
8
We create a 2D table dp of size(n) where each dp[i] is a map (hash table) storing the count of subsequences ending at index i for each common difference. The keys of the map are the common differences (diff), and the values are the counts of subsequences that end at arr[i] with that particular common difference (diff).
- dp[i][diff]: Represents the number of subsequences ending at index i with common difference diff.
- Base Case: Each element itself is an arithmetic subsequence of length 1.
For each pair of indices (i, j) where i > j: Calculate the common difference diff = arr[i] - arr[j].
- If subsequences with this diff exist at arr[j], extend them by adding arr[i].
- If no such subsequences exist at arr[j], start a new subsequence with (arr[j], arr[i]).
The total number of arithmetic subsequences will be the sum of all values in all maps at all indices i, i.e., sum(dp[i][diff]) for all i and diff.
8
Since empty sequence and single element sequence is also arithmetic progression, so we initialize the answer with n(number of element in the array) + 1.
Now, we need to find the arithmetic progression subsequence of length greater than or equal to 2. Let minimum and maximum of the array be minarr and maxarr respectively. Observe, in all the arithmetic progression subsequences, the range of common difference will be from (minarr - maxarr) to (maxarr - minarr). Now, for each common difference, say d, calculate the subsequence of length greater than or equal to 2 using dynamic programming.
The number of subsequence of length greater than or equal to 2 with common difference d is sum of dp[i] - 1, 0 <= i = 2 with difference d. To speed up, store the sum of dp[j] with arr[j] + d = arr[i] and j < i.
8