LC 392 & LC 115


Solution to LeetCode 392 Is Subsequence and LeetCode 115 Distinct Subsequences.

LeetCode 392

Is Subsequence (Easy) [link]

A subsequence of a string is a new string that is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (i.e., “ace” is a subsequence of “abcde” while “aec” is not).

Dynamic Programming. Define dp[i][j] as the length of common subsequence of s[0:i-1] and t[0:j-1]. (i-1 and j-1 because in this way we can leave room for initializing zeros at dp[i][0] and dp[0][j]). Case 1: if s[i - 1] == t[j - 1], then dp[i][j] = dp[i - 1][j - 1] + 1; Case 2: s[i - 1] != t[j - 1], then dp[i][j] = dp[i][j - 1].

Since updating dp[i][j] depends on dp[i-1][j-1] and dp[i][j-1], we need to initialize dp[0][0] and dp[i][0].

class Solution:
    def isSubsequence(self, s: str, t: str) -> bool:
        dp = [[0]*(len(t)+1) for _ in range(len(s)+1)]
        for i in range(1, len(s)+1):
            for j in range(1, len(t)+1):
                if s[i-1] == t[j-1]:
                    dp[i][j] = dp[i-1][j-1]+1
                else:
                    dp[i][j] = dp[i][j-1]
        if dp[-1][-1] == len(s):
            return True
        return False

LeetCode 115

Distinct Subsequences (Hard) [link]

Dynamic programming. Define dp[i][j] as the number of t[0:j-1] appearing in s[0:i-1].

Case1: s[i-1] == t[j-1]. We can either use s[i-1] to match or not use s[i-1] to match. If we use s[i-1] to match, dp[i][j] = dp[i-1][j-1]. If we don’t use s[i-1] to match, dp[i][j] = dp[i-1][j].

Case2: s[i-1] != t[j-1]. We don’t use s[i-1] to match, then dp[i][j] = dp[i - 1][j].

We need to initialize dp[i][0] and dp[0][j]. dp[i][0]=1 because we can delete all characters from s[i] to get an empty string. dp[0][j]=0 because we can never get a t[j] from an empty string s.

Time complexity O(n^2). Space complexity O(n^2).

class Solution:
    def numDistinct(self, s: str, t: str) -> int:
        dp = [[0]*(len(t)+1) for _ in range(len(s)+1)]
        for i in range(len(s)+1):
            dp[i][0] = 1
        # for j in range(1, len(t)+1):
        #     dp[0][j] = 0

        for i in range(1,len(s)+1):
            for j in range(1, len(t)+1):
                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 dp[-1][-1]

  TOC