Advertisement

Distinct Subsequences - LeetCode 115 Solution

Distinct Subsequences - Complete Solution Guide

Distinct Subsequences is LeetCode problem 115, a Hard level challenge. This complete guide provides step-by-step explanations, multiple solution approaches, and optimized code in python3, java, cpp, c.

Problem Statement

Given two strings s and t, return the number of distinct subsequences of s which equals t. The test cases are generated so that the answer fits on a 32-bit signed integer. Example 1: Input: s = "rabbbit", t = "rabbit" Output: 3 Explanation: As shown below, there are 3 ways you can generate "rabbit" from s. rabb b it ra b bbit rab b bit Example 2: Input: s = "babgbag", t = "bag" Output: 5 Explanation: As shown below, there are 5 ways you can generate "bag" from s. ba b g bag ba bgba g b abgb ag b

Detailed Explanation

The problem asks us to find the number of distinct subsequences of string `s` that are equal to string `t`. A subsequence is a sequence that can be derived from another sequence by deleting some or no elements without changing the order of the remaining elements. The task is to count how many different ways we can construct string `t` by selecting characters from string `s` in their original order.

Solution Approach

The solution employs dynamic programming to efficiently count the distinct subsequences. A 1D DP array `dp` of size `len(t) + 1` is used. `dp[j]` stores the number of distinct subsequences of the current prefix of `s` that match the prefix `t[0...j-1]`. The outer loop iterates through the `s` string, and the inner loop iterates backwards through the `t` string. If `s[i-1]` matches `t[j-1]`, it means we can either exclude `s[i-1]` or include it in forming the subsequence. Including it adds `dp[j-1]` to `dp[j]`, where `dp[j-1]` is the number of ways to form `t[0...j-2]` using `s[0...i-1]`. If `s[i-1]` doesn't match `t[j-1]`, we simply inherit the count from the previous state, meaning `dp[j]` remains unchanged for the current character in `s`.

Step-by-Step Algorithm

  1. Step 1: Initialize a 1D DP array `dp` of size `len(t) + 1` with all elements set to 0. `dp[0]` is set to 1, as an empty string `t` always exists as a subsequence of any string `s` exactly once (by deleting all characters of `s`).
  2. Step 2: Iterate through the string `s` from `i = 1` to `len(s)`. This represents considering each character of `s` one by one.
  3. Step 3: For each character in `s`, iterate through the string `t` from `j = len(t)` down to `1`. Iterating backwards avoids overwriting values needed in the current iteration when calculating `dp[j]` from `dp[j-1]`.
  4. Step 4: Inside the inner loop, check if `s[i - 1]` is equal to `t[j - 1]`. If they are equal, update `dp[j]` by adding `dp[j - 1]` to it. This means we can form the subsequence `t[0...j-1]` in two ways: by not including `s[i-1]` (already counted in `dp[j]`) or by including `s[i-1]` which requires `t[0...j-2]` to have been formed from `s[0...i-2]` which is `dp[j-1]`.
  5. Step 5: If `s[i - 1]` is not equal to `t[j - 1]`, then `dp[j]` remains unchanged, as `s[i-1]` doesn't contribute to forming `t[0...j-1]`.
  6. Step 6: After iterating through all characters of `s`, the final value of `dp[len(t)]` represents the total number of distinct subsequences of `s` that are equal to `t`.

Key Insights

  • Insight 1: Dynamic programming is suitable because the number of distinct subsequences can be built up from smaller subproblems.
  • Insight 2: The relationship dp[i][j] represents the number of distinct subsequences of s[0...i] which equals t[0...j].
  • Insight 3: Optimization is possible by reducing the space complexity from O(m*n) to O(n) by iterating backwards through the `t` string's indices.

Complexity Analysis

Time Complexity: O(m*n)

Space Complexity: O(n)

Topics

This problem involves: String, Dynamic Programming.

Companies

Asked at: Coupang, MathWorks, Salesforce, TikTok, Trilogy, Uber.