给定一个由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[] 的所有可能子集,如果存在任何子集的所有字符串都可以由给定的字母组成,那么通过添加使用的字母的成本来找到该子集的成本。请按照以下步骤解决问题:
- 维护一个频率数组freq[]来存储数组中字符的频率,字母。
- 调用递归函数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)
如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live