Post

3351. Sum of Good Subsequences

3351. Sum of Good Subsequences

Sum of Good Subsequences

image1

Approach to the Problem

We are tasked with finding the sum of all possible good subsequences in a given array nums where a good subsequence satisfies the condition that the absolute difference between any two consecutive elements is exactly 1. Here’s how we can systematically solve this problem.

Understand the Problem

  1. Subsequences: A subsequence is a sequence derived from an array by deleting some or no elements without changing the order of the remaining elements. Example: [1, 2, 1] has subsequences: [1], [2], [1], [1, 2], [2, 1], [1, 2, 1].
  2. Good Subsequences: A subsequence is good if the absolute difference between consecutive elements is exactly 1.
  3. Goal: Compute the sum of all good subsequences modulo 10⁹+7. Brute-Force Approach
  4. Generating All the Subsequences: Use recursion or bitmasking to generate all possible subsequences of the array. Check if each subsequence is good by ensuring the condition ∣a[i]−a[i−1]∣ = 1 is satisfied for all consecutive elements. Sum up all elements of the good subsequences.
  5. Time Complexity: Generating all subsequences takes O(2^n), where n is the length of the array. Verifying each subsequence for the good property takes O(n) in the worst case. Overall: O(n⋅2^n). This is infeasible for large n (up to 10⁵). Optimal Approach To handle the constraints efficiently, we use a dynamic programming approach with optimization based on frequencies of numbers in the array.

Algorithm We Use:-

  1. Frequency Array: Count the occurrences of each number in the array. This allows us to consider only the numbers present in the array, reducing unnecessary computation.
  2. Dynamic Programming Arrays: Using two arrays:

sum[c]: Tracks the sum of elements in all good subsequences ending with number c. count[c]: Tracks the number of good subsequences ending with number c. Transition: For each number c in nums:

Add contributions from subsequences ending at c-1 (if c-1 exists in the array). Add contributions from subsequences ending at c+1 (if c+1 exists in the array). Add the number c itself as a single-element subsequence. Modulo: Since the answer can be large, perform all computations modulo 10⁹+7. Final Sum: Sum up all values in the sum array to get the result.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
int sumOfGoodSubsequences(int[] nums) {
    int MOD = 1e9 + 7;
    int MAX = 1e5 + 1;

    long[] sum = new long[MAX];
    long[] count = new long[MAX];
    int[] freq = new int[MAX];

    // Count frequency of each number
    for (int num : nums) {
        freq[num]++;
    }

    for (int c = 0; c < MAX; c++) {
        if (freq[c] == 0) continue;

        if (c - 1 >= 0) {
            sum[c] += (count[c - 1] * c + sum[c - 1]) % MOD;
            count[c] += count[c - 1] % MOD;
        }

        sum[c] += c * freq[c];
        count[c] += freq[c];

        if (c + 1 < MAX) {
            sum[c] += (count[c + 1] * c + sum[c + 1]) % MOD;
            count[c] += count[c + 1] % MOD;
        }

        sum[c] %= MOD;
        count[c] %= MOD;
    }

    long result = 0;
    for (int c = 0; c < MAX; c++) {
        result = (result + sum[c]) % MOD;
    }

    return (int) result;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class Solution {
    public int sumOfGoodSubsequences(int[] nums) {
        long[] sum = new long[(int) (1e5 + 1)];
        long[] count = new long[(int) (1e5 + 1)];        
        int[] freq = new int[(int) (1e5 + 1)];
        long mod = (long) (1e9 + 7);
        for(int i: nums) freq[i]++;

        for(int i=0; i<nums.length; i++){
            int c = nums[i];
            if(c-1 >= 0 && count[c-1] > 0){
                sum[c] += (count[c-1] * c + sum[c-1]);
                count[c] += count[c-1];
            }
            sum[c] += c;
            count[c] += 1;

             if(c+1 < sum.length && count[c+1] > 0){
                sum[c] += (count[c+1] * c + sum[c+1]);
                count[c] += count[c+1];
            }
            sum[c] %= mod;
            count[c] %= mod;
        }
        long res = 0;
        for(int i=0; i < sum.length; ++i){
            if (sum[i] > 0){
                //system.out.println(i + "" + sum[i]);
            }
            res = (res % mod + sum[i] % mod) % mod;
        }

        return (int) (res % mod);
    } 
}

Time Complexity

Frequency Calculation: O(n), where n is the length of the array.

Dynamic Programming Update: O(range of numbers) = O(10⁵), as we iterate over the possible range of values.

Final Sum Computation: O(105)O(10⁵)O(105).

Overall Time Complexity: O(n+10⁵)≈ O(n) for n≤10⁵

Space Complexity

Frequency array: O(10⁵).

DP arrays (sum and count): O(10⁵).

Overall Space Complexity: O(10⁵).

How to Tackle Similar Problems

  1. Break Down the Problem: Identify properties of valid subsequences (like the condition ∣a[i]−a[i−1]∣=1|a[i] — a[i-1]| = 1∣a[i]−a[i−1]∣=1).
  2. Use Frequency Arrays: Preprocess the array to avoid redundant computation.
  3. Dynamic Programming: Use DP to build solutions iteratively while maintaining the necessary conditions.
  4. Modulo Arithmetic: Always consider constraints like modulo 10⁹+7 for large results.
This post is licensed under CC BY 4.0 by the author.