给定一个由N个字符串组成的数组arr [] ,由M个小写字符组成的数组letter []和一个数组score [] ,使得score [i]是第i个英语字母的代价,任务是找到最大值使用给定字母形成的任何有效单词集的成本,这样每个字母最多可以使用一次,每个单词arr [i]最多可以形成一次。
例子:
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:
The scores of ‘a’, ‘c’, ‘d’, ‘g’, and ‘o’ are 9, 5, 3, 2 respectively.
The score of the word “dad” = (5 + 1 + 5) = 11.
The score of the word “good” = (3 + 2 + 2 + 5) = 12.
Therefore, the total score = 11 + 12 = 23, which is maximum.
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
方法:可以通过使用递归来解决给定的问题。想法是生成给定数组arr []的所有可能子集,如果存在任何子集,其所有字符串都可以由给定字母组成,则通过添加所用字母的成本来找到该子集的成本。请按照以下步骤解决问题:
- 维持频率阵列,频率[]的字符的频率存储在数组中,字母。
- 调用递归函数helper() ,该函数以start (最初为0), words [] , freq []和score []数组作为参数。
- 当start = N时处理基本条件,然后返回0。
- 否则,将数组freq []的内容复制到另一个数组freqCopy []中。
- 将currScore和wordScore初始化为0,以存储最大分数和从当前单词获得的分数。
- 更新wordScore如果所有的当前字的它的字符,即字[开始]存在于阵列,freqCopy在,然后更新freqCopy。
- 通过将wordScore添加到递归调用函数helper()返回的值中,并通过将start + 1 , words [] , freqCopy []和score []数组作为参数传递来包含当前单词。
- 通过递归调用函数helper()并传递start + 1 , words [] , freq []和score []数组作为参数来排除当前单词。
- 将最高分数存储在currScore的两个分数中,并返回其值。
- 完成上述步骤后,打印由该函数返回的值。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Utility function to find
// maximum cost of generating
// any possible subsets of strings
int helper(vector words, int start,
vector letterCounts, vector score)
{
// Base Case
if (start == words.size())
return 0;
// Stores the current cost
int currScore = 0;
// Stores the cost of
// by the current word
int wordScore = 0;
// Create a copy of the
// letterCounts array
vector nextCounts = letterCounts;
// Traverse the current word
for (int i = 0;
i < words[start].size();
++i) {
// Store the current index & check
// if its frequency is 0 or not
int idx = words[start][i] - 'a';
if (nextCounts[idx] == 0) {
// If true, then update
// wordScore to -1
wordScore = -1;
break;
}
// Otherwise, add the cost of
// the current index to wordScore
wordScore += score[idx];
// Decrease its frequency
nextCounts[idx]--;
}
// If wordScore > 0, then
// recursively call for next index
if (wordScore > 0)
currScore = helper(words,
start + 1,
nextCounts,
score)
+ wordScore;
// Find the cost by not
// including current word
currScore = max(
currScore, helper(words, start + 1,
letterCounts,
score));
// Return the maximum score
return currScore;
}
// Function to find the maximum cost
// of any valid set of words formed
// by using the given letters
int maxScoreWords(vector words, vector letters,
vector score)
{
// Stores frequency of characters
vector letterCounts(26,0);
for (char letter : letters)
letterCounts[letter - 'a']++;
// Find the maximum cost
return helper(words, 0,
letterCounts,
score);
}
// Driver Code
int main()
{
// Given arrays
vector words = { "dog", "cat", "dad", "good" };
vector letters = { 'a', 'a', 'c', 'd', 'd','d', 'g', 'o', 'o' };
vector 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 };
// Function Call
cout<<(maxScoreWords(words, letters, score));
}
// This code is contributed by mohit kumar 29.
Java
// Java program for the above approach
import java.io.*;
class GFG {
// Function to find the maximum cost
// of any valid set of words formed
// by using the given letters
public static int maxScoreWords(
String[] words, char[] letters,
int[] score)
{
// Stores frequency of characters
int[] letterCounts = new int[26];
for (char letter : letters)
letterCounts[letter - 'a']++;
// Find the maximum cost
return helper(words, 0,
letterCounts,
score);
}
// Utility function to find
// maximum cost of generating
// any possible subsets of strings
public static int helper(
String[] words, int start,
int[] letterCounts, int[] score)
{
// Base Case
if (start == words.length)
return 0;
// Stores the current cost
int currScore = 0;
// Stores the cost of
// by the current word
int wordScore = 0;
// Create a copy of the
// letterCounts array
int[] nextCounts
= letterCounts.clone();
// Traverse the current word
for (int i = 0;
i < words[start].length();
++i) {
// Store the current index & check
// if its frequency is 0 or not
int idx = words[start].charAt(i) - 'a';
if (nextCounts[idx] == 0) {
// If true, then update
// wordScore to -1
wordScore = -1;
break;
}
// Otherwise, add the cost of
// the current index to wordScore
wordScore += score[idx];
// Decrease its frequency
nextCounts[idx]--;
}
// If wordScore > 0, then
// recursively call for next index
if (wordScore > 0)
currScore = helper(words,
start + 1,
nextCounts,
score)
+ wordScore;
// Find the cost by not
// including current word
currScore = Math.max(
currScore, helper(words, start + 1,
letterCounts,
score));
// Return the maximum score
return currScore;
}
// Driver Code
public static void main(String[] args)
{
// Given arrays
String words[] = { "dog", "cat", "dad", "good" };
char letters[] = { 'a', 'a', 'c', 'd', 'd',
'd', 'g', 'o', 'o' };
int 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 };
// Function Call
System.out.println(
maxScoreWords(words, letters, score));
}
}
C#
// C# program for the above approach
using System;
using System.Linq;
class GFG
{
// Function to find the maximum cost
// of any valid set of words formed
// by using the given letters
public static int maxScoreWords(
string[] words, char[] letters,
int[] score)
{
// Stores frequency of characters
int[] letterCounts = new int[26];
foreach (char letter in letters)
letterCounts[letter - 'a']++;
// Find the maximum cost
return helper(words, 0,
letterCounts,
score);
}
// Utility function to find
// maximum cost of generating
// any possible subsets of strings
public static int helper(
string[] words, int start,
int[] letterCounts, int[] score)
{
// Base Case
if (start == words.Length)
return 0;
// Stores the current cost
int currScore = 0;
// Stores the cost of
// by the current word
int wordScore = 0;
// Create a copy of the
// letterCounts array
int[] nextCounts
= letterCounts.ToArray();
// Traverse the current word
for (int i = 0;
i < words[start].Length;
++i) {
// Store the current index & check
// if its frequency is 0 or not
int idx = words[start][i] - 'a';
if (nextCounts[idx] == 0) {
// If true, then update
// wordScore to -1
wordScore = -1;
break;
}
// Otherwise, add the cost of
// the current index to wordScore
wordScore += score[idx];
// Decrease its frequency
nextCounts[idx]--;
}
// If wordScore > 0, then
// recursively call for next index
if (wordScore > 0)
currScore = helper(words,
start + 1,
nextCounts,
score)
+ wordScore;
// Find the cost by not
// including current word
currScore = Math.Max(
currScore, helper(words, start + 1,
letterCounts,
score));
// Return the maximum score
return currScore;
}
// Driver Code
public static void Main(string[] args)
{
// Given arrays
string []words = { "dog", "cat", "dad", "good" };
char []letters = { 'a', 'a', 'c', 'd', 'd',
'd', 'g', 'o', 'o' };
int []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 };
// Function Call
Console.WriteLine(
maxScoreWords(words, letters, score));
}
}
// This code is contributed by ukasp.
Java
// Java program for the above approach
import java.io.*;
import java.util.*;
class GFG {
// Function to find the maximum cost
// of any valid set of words formed
// by using the given letters
public static int maxScoreWords(
String[] words, char[] letters,
int[] score)
{
// Stores frequency of characters
int[] letterCounts = new int[26];
for (char letter : letters)
letterCounts[letter - 'a']++;
// Function Call to find the
// maximum cost
return helper(words, 0, letterCounts,
score,
new HashMap<>());
}
// Utility function to find maximum
// cost of generating any possible
// subsets of strings
public static int helper(
String[] words, int start,
int[] letterCounts, int[] score,
Map memo)
{
// Base Case
if (start == words.length)
return 0;
// If the score for this call
// is already computed, then
// return result from hashmap
String key = getKey(letterCounts, start);
if (memo.containsKey(key))
return memo.get(key);
// Store the current score
int currScore = 0;
// Stores the cost contributed
// by the current word
int wordScore = 0;
// Create a copy of the
// letterCounts array
int[] nextCounts = letterCounts.clone();
// Traverse the current word
// i.e., words[start]
for (int i = 0;
i < words[start].length();
++i) {
// Store the current index
// & check if its frequency
// is 0 or not
int idx = words[start].charAt(i) - 'a';
if (nextCounts[idx] == 0) {
// If true, then update
// wordScore to -1 and
// break
wordScore = -1;
break;
}
// Otherwise, add the cost
// of the current index to
// wordScore and decrease
// its frequency
wordScore += score[idx];
nextCounts[idx]--;
}
// If wordScore > 0, then
// recursively call for the
// next index
if (wordScore > 0)
currScore = helper(words, start + 1,
nextCounts,
score, memo)
+ wordScore;
// Find the cost by not including
// the current word
currScore = Math.max(
currScore, helper(words, start + 1,
letterCounts, score,
memo));
// Memoize the result
memo.put(key, currScore);
// Return the maximum score
return currScore;
}
// Function to get the unique key
// from the letterCounts array
// with their index
public static String getKey(
int[] letterCounts, int idx)
{
// Append the frequency of
// each character
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 26; ++i)
sb.append(letterCounts[i]);
// Append the index
sb.append(', ');
sb.append(idx);
// Return the string
return sb.toString();
}
// Driver Code
public static void main(String[] args)
{
String words[] = { "dog", "cat", "dad", "good" };
char letters[] = { 'a', 'a', 'c', 'd', 'd',
'd', 'g', 'o', 'o' };
int 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 };
System.out.println(
maxScoreWords(words, letters,
score));
}
}
23
时间复杂度: O(2 N )
辅助空间: O(26)
高效方法:通过观察上述问题具有最优子结构和重叠子问题的事实,也可以优化上述方法。因此,其思想是记住每个递归调用中的结果,并在执行相同的递归调用时使用那些存储的状态。为了存储每个递归调用,请使用HashMap。
下面是上述方法的实现:
Java
// Java program for the above approach
import java.io.*;
import java.util.*;
class GFG {
// Function to find the maximum cost
// of any valid set of words formed
// by using the given letters
public static int maxScoreWords(
String[] words, char[] letters,
int[] score)
{
// Stores frequency of characters
int[] letterCounts = new int[26];
for (char letter : letters)
letterCounts[letter - 'a']++;
// Function Call to find the
// maximum cost
return helper(words, 0, letterCounts,
score,
new HashMap<>());
}
// Utility function to find maximum
// cost of generating any possible
// subsets of strings
public static int helper(
String[] words, int start,
int[] letterCounts, int[] score,
Map memo)
{
// Base Case
if (start == words.length)
return 0;
// If the score for this call
// is already computed, then
// return result from hashmap
String key = getKey(letterCounts, start);
if (memo.containsKey(key))
return memo.get(key);
// Store the current score
int currScore = 0;
// Stores the cost contributed
// by the current word
int wordScore = 0;
// Create a copy of the
// letterCounts array
int[] nextCounts = letterCounts.clone();
// Traverse the current word
// i.e., words[start]
for (int i = 0;
i < words[start].length();
++i) {
// Store the current index
// & check if its frequency
// is 0 or not
int idx = words[start].charAt(i) - 'a';
if (nextCounts[idx] == 0) {
// If true, then update
// wordScore to -1 and
// break
wordScore = -1;
break;
}
// Otherwise, add the cost
// of the current index to
// wordScore and decrease
// its frequency
wordScore += score[idx];
nextCounts[idx]--;
}
// If wordScore > 0, then
// recursively call for the
// next index
if (wordScore > 0)
currScore = helper(words, start + 1,
nextCounts,
score, memo)
+ wordScore;
// Find the cost by not including
// the current word
currScore = Math.max(
currScore, helper(words, start + 1,
letterCounts, score,
memo));
// Memoize the result
memo.put(key, currScore);
// Return the maximum score
return currScore;
}
// Function to get the unique key
// from the letterCounts array
// with their index
public static String getKey(
int[] letterCounts, int idx)
{
// Append the frequency of
// each character
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 26; ++i)
sb.append(letterCounts[i]);
// Append the index
sb.append(', ');
sb.append(idx);
// Return the string
return sb.toString();
}
// Driver Code
public static void main(String[] args)
{
String words[] = { "dog", "cat", "dad", "good" };
char letters[] = { 'a', 'a', 'c', 'd', 'd',
'd', 'g', 'o', 'o' };
int 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 };
System.out.println(
maxScoreWords(words, letters,
score));
}
}
23
时间复杂度: O(N * X),其中X是words []数组中最大字符串的大小。
辅助空间: O(N)