g0601_0700.s0691_stickers_to_spell_word.Solution Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of leetcode-in-java21 Show documentation
Show all versions of leetcode-in-java21 Show documentation
Java-based LeetCode algorithm problem solutions, regularly updated
package g0601_0700.s0691_stickers_to_spell_word;
// #Hard #Array #String #Dynamic_Programming #Bit_Manipulation #Backtracking #Bitmask
// #2022_03_22_Time_34_ms_(70.23%)_Space_54.1_MB_(35.88%)
import java.util.HashMap;
import java.util.HashSet;
/**
* 691 - Stickers to Spell Word\.
*
* Hard
*
* 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 <= 15`
* * `stickers[i]` and `target` consist of lowercase English letters.
**/
public class Solution {
// count the characters of every sticker
private int[][] counts;
// For each character, save the sticker index which has this character
private HashMap> map = new HashMap<>();
private HashMap cache = new HashMap<>();
public int minStickers(String[] stickers, String target) {
counts = new int[stickers.length][26];
for (int i = 0; i < 26; i++) {
map.put((char) ('a' + i), new HashSet<>());
}
for (int i = 0; i < stickers.length; i++) {
for (char c : stickers[i].toCharArray()) {
counts[i][c - 'a']++;
map.get(c).add(i);
}
}
int res = dp(0, target);
if (res > target.length()) {
return -1;
}
return res;
}
private int dp(int bits, String target) {
int len = target.length();
if (bits == (1 << len) - 1) {
// all bits are 1
return 0;
}
if (cache.containsKey(bits)) {
return cache.get(bits);
}
int index = 0;
// find the first bit which is 0
for (int i = 0; i < len; i++) {
if ((bits & (1 << i)) == 0) {
index = i;
break;
}
}
// In worst case, each character use 1 sticker. So, len + 1 means impossible
int res = len + 1;
for (int key : map.get(target.charAt(index))) {
int[] count = counts[key].clone();
int mask = bits;
for (int i = index; i < len; i++) {
if ((mask & (1 << i)) != 0) {
// this bit has already been 1
continue;
}
char c = target.charAt(i);
if (count[c - 'a'] > 0) {
count[c - 'a']--;
mask |= (1 << i);
}
}
int val = dp(mask, target) + 1;
res = Math.min(res, val);
}
cache.put(bits, res);
return res;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy