构建目标字符串所需的最少字数
给定一个字符串数组,大小为M的words[]和大小为N的字符串目标。任务是通过从单词集合中剪切单个字母并重新排列它们来找到拼出字符串目标所需的最小单词数,前提是每个单词有无限的供应量。如果不可能,打印-1。
例子:
Input: words[] = {“with”, “example”, “science”}, target = “thehat”
Output: 3
Explanation: The target string, “thehat” consists of {‘h’ = 2, ‘t’ = 2, ‘e’ = 1, ‘a’ = 1}.
The two “with” strings are required to get two ‘h’ and two ‘t’ and one “example” string is required to get one ‘e’ and one ‘a’ to form the target string “thehat”.
So, total word required to construct the given target is 3.
Input: words[] = {“notice”, “possible”}, target = “basicbasic”
Output: -1
Explanation: It is not possible to form the given target string.
方法:这个想法是使用回溯。请按照以下步骤解决问题:
- 声明一个二维数组,比如countMap[][],其中countMap[i][j]存储第i个字符串中第j个字符的计数。
- 声明一个数组charAvavilable[26],表示当前可用字符数。
- 定义一个递归函数,它将当前索引i (最初为 0) 的字符串, target作为输入。
- 如果当前计数大于总计数,则返回。此外,如果当前索引i等于N ,则更新总计数并返回。
- 如果charAvailable[]中出现target[i] ,
- 减少charAvailable[]中字符target[i]的出现次数。
- 递归调用索引i+1 ,同时将计数更新 1。
- 在函数调用后将字符target[i]的出现增加 1 以进行回溯。
- 否则,迭代countMap[][]以查找target[i]的出现。如果找到,则通过将 count 更新 1 来递归调用该函数,并在函数调用之后执行回溯步骤。
- 打印所需的最少字数。
下面是上述方法的实现:
C++
// C++ program of the above approach
#include
using namespace std;
// countMap[][] to store
// count of characters
vector > countMap;
int cnt = INT_MAX;
// Function to get minimum number of
// stickers for a particular state
void count(int curCnt, int pos, vectorcharAvailable,
string target, vector stickers)
{
// If an optimal solution is
// already there, return
if (curCnt >= cnt)
return;
int m = stickers.size();
int n = target.size();
// If Target has been constructed
// update cnt and return
if (pos == n)
{
cnt = min(cnt, curCnt);
return;
}
char c = target[pos];
if (charAvailable > 0)
{
// Update charAvailable[]
charAvailable--;
// Recursizevely function call
// for (pos + 1)
count(curCnt, pos + 1, charAvailable,
target, stickers);
// Update charAvailable[]
charAvailable++;
}
else
{
for(int i = 0; i < m; i++)
{
if (countMap[i] == 0)
continue;
// Update charAvailable[]
for(int j = 0; j < 26; j++)
{
charAvailable[j] += countMap[i][j];
}
// Recursizeve Call
count(curCnt + 1, pos, charAvailable,
target, stickers);
// Update charAvailable[]
for(int j = 0; j < 26; j++)
{
charAvailable[j] -= countMap[i][j];
}
}
}
}
// Function to find the minimum
// number of stickers
int minStickers(vector stickers,
string target)
{
// Base Case
if (target == "")
return -1;
if (target.size() == 0)
return 0;
if (stickers.size() == 0)
return -1;
int m = stickers.size();
countMap.resize(m, vector(26, 0));
// Fill the countMap Array
for(int i = 0; i < stickers.size(); i++)
{
string s = stickers[i];
for(char c : s)
{
countMap[i]++;
}
}
// Recusizeve function call to get
// minimum number of stickers
vector temp(26);
count(0, 0, temp, target, stickers);
return cnt == INT_MAX ? -1 : cnt;
}
// Driver Code
int main()
{
// Given Input
vector str = {"with", "example", "science"};
string target = "thehat";
// Function Call
int Result = minStickers(str, target);
// Print the result
cout << Result;
}
// This code is contributed by mohit kumar 29
Java
// Java program of the above approach
import java.io.*;
import java.util.*;
class Sol {
// countMap[][] to store
// count of characters
int[][] countMap;
int cnt = Integer.MAX_VALUE;
// Function to find the minimum
// number of stickers
public int minStickers(String[] stickers
, String target)
{
// Base Case
if (target == null)
return -1;
if (target.length() == 0)
return 0;
if (stickers == null || stickers.length == 0)
return -1;
int m = stickers.length;
countMap = new int[m][26];
// Fill the countMap Array
for (int i = 0; i < stickers.length; i++) {
String s = stickers[i];
for (char c : s.toCharArray()) {
countMap[i]++;
}
}
// Recursive function call to get
// minimum number of stickers
count(0, 0, new int[26], target, stickers);
return cnt == Integer.MAX_VALUE ? -1 : cnt;
}
// Function to get minimum number of
// stickers for a particular state
private void count(int curCnt, int pos,
int[] charAvailable, String target,
String[] stickers)
{
// If an optimal solution is
// already there, return
if (curCnt >= cnt)
return;
int m = stickers.length;
int n = target.length();
// If Target has been constructed
// update cnt and return
if (pos == n) {
cnt = Math.min(cnt, curCnt);
return;
}
char c = target.charAt(pos);
if (charAvailable > 0) {
// Update charAvailable[]
charAvailable--;
// Recursively function call
// for (pos + 1)
count(curCnt, pos + 1, charAvailable, target,
stickers);
// Update charAvailable[]
charAvailable++;
}
else {
for (int i = 0; i < m; i++) {
if (countMap[i] == 0)
continue;
// Update charAvailable[]
for (int j = 0; j < 26; j++) {
charAvailable[j] += countMap[i][j];
}
// Recursive Call
count(curCnt + 1, pos, charAvailable,
target, stickers);
// Update charAvailable[]
for (int j = 0; j < 26; j++) {
charAvailable[j] -= countMap[i][j];
}
}
}
}
}
class GFG {
// Driver Code
public static void main(String[] args)
{
Sol st = new Sol();
// Given Input
String[] str = { "with", "example", "science" };
String target = "thehat";
// Function Call
int Result = st.minStickers(str, target);
// Print the result
System.out.println(Result);
}
}
3
时间复杂度: O(M*26*2 N )
辅助空间: O(M*26)