691 Stickers to Spell Word
1. Question
We are given N different types of stickers. Each sticker has a lowercase English word on it.
You would like to spell out the giventarget
string 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.
What is the minimum number of stickers that you need to spell out thetarget
? If the task is impossible, return -1.
Example 1:
Input:
Output:
Explanation:
Example 2:
Input:
Output:
Explanation:
Note:
stickers
has length in the range[1, 50]
.
stickers
consists of lowercase English words (without apostrophes).
target
has length in the range[1, 15]
, and consists of lowercase English letters.
In all test cases, all words were chosen randomly from the 1000 most common US English words, and the target was chosen as a concatenation of two random words.
The time limit may be more challenging than usual. It is expected that a 50 sticker test case can be solved within 35ms on average.
2. Implementation
(1) Bitmap + DP
思路: 这道题很巧妙,运用了位图法和DP才能做出来。题目要求用最少的sticker得到target string。对于一个target string,它所包含的集合数为 2 ^ n。
(1) 假设target string是abc, 那么bitmap里每个subset的bit mask和所包含的character可表示为如下表格:
Subset
Bitmask
""
0
c
001
b
010
bc
011
a
100
ac
101
ab
110
abc
111
不难发现,bitmask上的1代表target string里对应的位置上的character包含在subset里
(2) 我们已经知道如何用bitmap表示target string的不同subset,接下来的问题是我们怎么知道每个subset需要最少多少个sticker?
根据动态规划的思想,我们定义dp[i]为第i个subset需要的sticker的最少数量,我们将这个数组初始化为Integer.MAXVALUE, 显然,空集合不需要任何sticker,所以有dp[0] = 0。 接着对于每个subset,我们只要遍历所有的sticker,然后对于每个sticker的每个character,我们检查target是否含有该character,如果有并且当前的subset不包含该character的话,我们将character加进subset中(通过位运算的方法mark该character已被选取),这样我们得到一个新的subset,直到当遍历完一个sticker后,我们就知道通过现在的sticker,我们可以从开始的subset i 到达哪个一个subset,然后dp[curSet] = Math.min(dp[curSet], dp[i] + 1)
代码实现如下:
3. Time & Space Complexity
(1) Bitmap + DP: 时间复杂度O(2^n * s * l * n), n为target string的长度, s为sticker的个数, l为sticker的平均长度,空间复杂度O(2^n),
Last updated
Was this helpful?