Complete-Preparation

πŸŽ‰ One-stop destination for all your technical interview Preparation πŸŽ‰

View the Project on GitHub

Distinct Subsequences 🌟🌟🌟

Given two strings s and t, return the number of distinct subsequences of s which equals t.

A string’s subsequence is a new string formed from the original string by deleting some (can be none) of the characters without disturbing the remaining characters’ relative positions. (i.e., β€œACE” is a subsequence of β€œABCDE” while β€œAEC” is not).

The test cases are generated so that the answer fits on a 32-bit signed integer.

Recursive Approach

Code

class Solution {
    int f(int i, int j, string& s, string& t)
    {
        if (j < 0) return 1;
        if (i < 0) return 0;

        if (s[i] == t[j]) {
            int take = f(i - 1, j - 1, s, t);
            int notTake = f(i - 1, j, s, t);
            return take + notTake;
        }
        int reduce = f(i - 1, j, s, t);
        return reduce;
    }

public:
    int numDistinct(string s, string t)
    {
        int n = s.size(), m = t.size();
        return f(n - 1, m - 1, s, t);
    }
};

Memoization(Top-Down)

Code-1

class Solution {
    int f(int i, int j, string& s, string& t, vector<vector<double>>& dp)
    {
        if (j < 0) return 1;
        if (i < 0) return 0;

        if (dp[i][j] != -1) return dp[i][j];

        if (s[i] == t[j]) {
            int take = f(i - 1, j - 1, s, t, dp);
            int notTake = f(i - 1, j, s, t, dp);
            return dp[i][j] = take + notTake;
        }
        int reduce = f(i - 1, j, s, t, dp);
        return dp[i][j] = reduce;
    }

public:
    int numDistinct(string s, string t)
    {
        int n = s.size(), m = t.size();
        vector<vector<double>> dp(n, vector<double>(m, -1));
        return f(n - 1, m - 1, s, t, dp);
    }
};

Code-2

class Solution {
    int f(int i, int j, string& s, string& t, vector<vector<double>>& dp)
    {
        if (j == 0) return 1;
        if (i == 0) return 0;

        if (dp[i][j] != -1) return dp[i][j];

        if (s[i - 1] == t[j - 1]) {
            int take = f(i - 1, j - 1, s, t, dp);
            int notTake = f(i - 1, j, s, t, dp);
            return dp[i][j] = take + notTake;
        }
        int reduce = f(i - 1, j, s, t, dp);
        return dp[i][j] = reduce;
    }

public:
    int numDistinct(string s, string t)
    {
        int n = s.size(), m = t.size();
        vector<vector<double>> dp(n + 1, vector<double>(m + 1, -1));
        return f(n, m, s, t, dp);
    }
};

Tabulation(Bottom-Up)

Code

class Solution {
public:
    int numDistinct(string s, string t)
    {
        int n = s.size();
        int m = t.size();
        vector<vector<double>> dp(n + 1, vector<double>(m + 1, 0));
        for (int i = 0; i <= n; i++) {
            dp[i][0] = 1;
        }
        for (int i = 1; i <= n; i++) {
            for (int j = m; j >= 1; j--) { // both reverse and normal order works
                if (s[i - 1] == t[j - 1]) {
                    dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];
                } else {
                    dp[i][j] = dp[i - 1][j];
                }
            }
        }
        return (int)dp[n][m];
    }
};

Space Optimized Tabulation

Code

class Solution {
public:
    int numDistinct(string s, string t)
    {
        int n = s.size(), m = t.size();
        vector<double> prev(m + 1, 0), curr(m + 1, 0);

        prev[0] = curr[0] = 1;

        for (int i = 1; i <= n; i++) {
            for (int j = m; j >= 1; j--) {
                if (s[i - 1] == t[j - 1]) {
                    curr[j] = prev[j - 1] + prev[j];
                } else {
                    curr[j] = prev[j];
                }
            }
            prev = curr;
        }
        return (int)prev[m];
    }
};

Space Optimized Tabulation 1 Array

class Solution {
public:
    int numDistinct(string s, string t)
    {
        int n = s.size(), m = t.size();
        vector<double> dp(m + 1, 0);

        dp[0] = 1;

        for (int i = 1; i <= n; i++) {
            for (int j = m; j >= 1; j--) {
                if (s[i - 1] == t[j - 1]) {
                    dp[j] = dp[j - 1] + dp[j];
                }
            }
        }
        return (int)dp[m];
    }
};