1 minute read

Problem Statement

problem-2370

Memoization approach - Memory Limit Exceeded

class Solution:
    def longestIdealString(self, s: str, k: int) -> int:
        res = float('-inf')
        @cache
        def dfs(i, curr, length):
            if i >= len(s):
                return length

            take = skip = 0
            if abs(ord(s[i]) - ord(curr)) <= k:
                take = dfs(i + 1, s[i], length + 1)
            skip = dfs(i + 1, curr, length)
            return max(take, skip)

        for i in range(len(s)):
            res = max(res, dfs(i + 1, s[i], 1))

        return res if res != float('-inf') else 1

Editorial Solution

Top down - memoization approach

class Solution:
    def longestIdealString(self, s: str, k: int) -> int:
        N = len(s)

        # Initialize all dp values to -1 to indicate non-visited states
        dp = [[-1] * 26 for _ in range(N)]

        def dfs(i: int, c: int, dp: list, s: str, k: int) -> int:
            # Memoized value
            if dp[i][c] != -1:
                return dp[i][c]

            # State is not visited yet
            dp[i][c] = 0
            match = c == (ord(s[i]) - ord('a'))
            if match:
                dp[i][c] = 1

            # Non base case handling
            if i > 0:
                dp[i][c] = dfs(i - 1, c, dp, s, k)
                if match:
                    for p in range(26):
                        if abs(c - p) <= k:
                            dp[i][c] = max(dp[i][c], dfs(i - 1, p, dp, s, k) + 1)
            return dp[i][c]

        # Find the maximum dp[N-1][c] and return the result
        res = 0
        for c in range(26):
            res = max(res, dfs(N - 1, c, dp, s, k))
        return res

Bottom up - dynamic programming

class Solution:
    def longestIdealString(self, s: str, k: int) -> int:
        N = len(s)
        dp = [0] * 26

        res = 0
        # Updating dp with the i-th character
        for i in range(N):
            curr = ord(s[i]) - ord('a')
            best = 0
            for prev in range(26):
                if abs(prev - curr) <= k:
                    best = max(best, dp[prev])

            # Append s[i] to the previous longest ideal subsequence
            dp[curr] = max(dp[curr], best + 1)
            res = max(res, dp[curr])
        return res