Problem
Given a list of words
, list of single letters
(might be repeating) and score
of every character.
Return the maximum score of any valid set of words formed by using the given letters (words[i]
cannot be used two or more times).
It is not necessary to use all characters in letters
and each letter can only be used once. Score of letters 'a'
, 'b'
, 'c'
, … ,'z'
is given by score[0]
, score[1]
, … , score[25]
respectively.
Examples
Example 1:
Input: words = ["dog","cat","dad","good"], letters = ["a","a","c","d","d","d","g","o","o"], score = [1,0,9,5,0,0,3,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0]
Output: 23
Explanation:
Score a=1, c=9, d=5, g=3, o=2
Given letters, we can form the words "dad" (5+1+5) and "good" (3+2+2+5) with a score of 23.
Words "dad" and "dog" only get a score of 21.
Example 2:
Input: words = ["xxxz","ax","bx","cx"], letters = ["z","a","b","c","x","x","x"], score = [4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,10]
Output: 27
Explanation:
Score a=4, b=4, c=4, x=5, z=10
Given letters, we can form the words "ax" (4+5), "bx" (4+5) and "cx" (4+5) with a score of 27.
Word "xxxz" only get a score of 25.
Example 3:
Input: words = ["leetcode"], letters = ["l","e","t","c","o","d"], score = [0,0,1,1,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0]
Output: 0
Explanation:
Letter "e" can only be used once.
Solution
Method 1 - Backtracking
We start in a similar way to Subsets Problem, and try to form set of words.
Here is the video explanation:
Code
Java
Variant 1 - Include and exclude logic
class Solution {
public int maxScoreWords(String[] words, char[] letters, int[] score) {
int[] count = new int[score.length];
for (char ch : letters) {
count[ch - 'a']++;
}
return backtrack(words, count, score, 0);
}
int backtrack(String[] words, int[] count, int[] score, int idx) {
if (idx == words.length) {
return 0;
}
int ans = 0;
int curr = 0;
boolean isValid = true;
for (char ch : words[idx].toCharArray()) {
count[ch - 'a']--;
curr += score[ch - 'a'];
if (count[ch - 'a'] < 0) {
isValid = false;
}
}
if (isValid) {
// include
ans = backtrack(words, count, score, idx + 1) + curr;
}
// revert counts array
for (char ch : words[idx].toCharArray()) {
count[ch - 'a']++;
}
ans = Math.max(ans, backtrack(words, count, score, idx + 1));
return ans;
}
}
Variant 2 - Going to all elements
class Solution {
public int maxScoreWords(String[] words, char[] letters, int[] score) {
int[] count = new int[score.length];
for (char ch : letters) {
count[ch - 'a']++;
}
return backtrack(words, count, score, 0);
}
int backtrack(String[] words, int[] count, int[] score, int idx) {
int ans = 0;
for (int i = idx; i < words.length; i++) {
int curr = 0;
boolean isValid = true;
for (char ch : words[i].toCharArray()) {
count[ch - 'a']--;
curr += score[ch - 'a'];
if (count[ch - 'a'] < 0) {
isValid = false;
}
}
if (isValid) {
curr += backtrack(words, count, score, i + 1);
ans = Math.max(ans, curr);
}
for (char ch : words[i].toCharArray()) {
count[ch - 'a']++;
curr = 0;
}
}
return ans;
}
}
Complexity
- ⏰ Time complexity:
O(n*l*2^n)
-n
- number of words,l
- average length of the words. (We also change count array, but that multiplies time complexity by 26, which is constant). - 🧺 Space complexity:
O(n)
Dry Run
We start first by creating frequency map (count
array) for given letters
. count
array initially: {'a': 2, 'c': 1, 'd': 3, 'g': 1, 'o': 2}
.
Lets calculate the score of each word, for our understanding, assuming we are able to form it:
idx = 0
, Word = “dog”
- “dog” can be formed using
{'d': 1, 'o': 1, 'g': 1}
- Score: 5 + 2 + 3 = 10
count = {'a': 2, 'c': 1, 'd': 2, 'g': 0, 'o': 1}
idx = 1
, Word = “cat”
- “cat” cannot be formed (not enough ’t’), so we skip
idx = 2
, Word = “dad”
- “dad” can be formed using
{'d': 2, 'a': 1}
- Score: 5 + 1 + 5 = 11.
count = {'a': 1, 'c': 1, 'd': 1, 'g': 1, 'o': 2}
idx = 3
, Word = “good”
- “good” can be formed using {‘g’: 1, ‘o’: 2, ’d’: 1}
- Score: 3 + 0 + 0 + 3 = 6
count = {'a': 2, 'c': 1, 'd': 2, 'g': 0, 'o': 0}
Recursive depth from different levels
We start with idx = 0
.
We now start DFS on words = ["dog","cat","dad","good"]
.