Solving Leetcode Interviews in Seconds with AI: Stickers to Spell Word
Introduction
In this blog post, we will explore how to solve the LeetCode problem "691" using AI. LeetCode is a popular platform for preparing for coding interviews, and with the help of AI tools like Chatmagic, we can generate solutions quickly and efficiently - helping you pass the interviews and get the job offer without having to study for months.
Problem Statement
We are given n different types of stickers. Each sticker has a lowercase English word on it. You would like to spell out the given string target by cutting individual letters from your collection of stickers and rearranging them. You can use each sticker more than once if you want, and you have infinite quantities of each sticker. Return the minimum number of stickers that you need to spell out target. If the task is impossible, return -1. Note: In all test cases, all words were chosen randomly from the 1000 most common US English words, and target was chosen as a concatenation of two random words. Example 1: Input: stickers = ["with","example","science"], target = "thehat" Output: 3 Explanation: We can use 2 "with" stickers, and 1 "example" sticker. After cutting and rearrange the letters of those stickers, we can form the target "thehat". Also, this is the minimum number of stickers necessary to form the target string. Example 2: Input: stickers = ["notice","possible"], target = "basicbasic" Output: -1 Explanation: We cannot form the target "basicbasic" from cutting letters from the given stickers. Constraints: n == stickers.length 1 <= n <= 50 1 <= stickers[i].length <= 10 1 <= target.length <= 15 stickers[i] and target consist of lowercase English letters.
Explanation
Here's a breakdown of the solution:
Dynamic Programming: We use dynamic programming to store the minimum number of stickers needed to form prefixes of the target string. The
dparray stores the minimum stickers needed for each prefix.Greedy Optimization: For each prefix, we iterate through the stickers. For each sticker, we try to reduce the prefix by using the letters in the sticker greedily. We prioritize stickers that contribute significantly to forming the current prefix.
Base Case and Memoization: The base case is an empty string, which requires 0 stickers. The
dparray memoizes the results, avoiding redundant calculations. If a target or any prefix of it can not be formed, the value in dp array remains infinity and we return -1.Complexity: O(2T S L), where T is the length of the target, S is the number of stickers, and L is the average length of a sticker. The storage complexity is O(T). Note that the 2T is the theoretical upper bound to the number of possible states, the actual states we compute via DP are much less.
Code
from collections import Counter
def minStickers(stickers, target):
n = len(target)
dp = {} # dp[target] = min stickers needed to form target
def solve(remaining):
if not remaining:
return 0
if remaining in dp:
return dp[remaining]
dp[remaining] = float('inf')
for sticker in stickers:
new_remaining = ""
sticker_counts = Counter(sticker)
remaining_counts = Counter(remaining)
for char in remaining:
if sticker_counts[char] > 0:
sticker_counts[char] -= 1
else:
new_remaining += char
if len(new_remaining) < len(remaining):
res = solve(new_remaining)
if res != float('inf'):
dp[remaining] = min(dp[remaining], 1 + res)
return dp[remaining]
result = solve(target)
return result if result != float('inf') else -1