题目
**给定一个字符串str,给定一一个字符串类型的数组arr。
arr里的每一个字符串,代表一张贴纸,你可以把单个字符剪开使用,目的是拼出str来。
返回需要至少多少张贴纸可以完成这个任务。
例子: str= “babac”,arr = {“ba”,“c”,“abcd”}
至少需要两张贴纸"ba"和"abcd",因为使用这两张贴纸,把每一个字符单独剪开,含有2个a、2个b、1个c。是可以拼出str的。所以返回2。
提示:可变参数能少则少,可变参数越少,缓存结构的命中率越高**
package com.harrison.class13;
import java.util.HashMap;
public class Code07_StickersToSpellWord {
// 伪代码
// public static int getMinStickers(String rest,String[] arr) {
// // 加过滤 保证所有贴纸里的字符能够覆盖目标字符串
// }
//
// public static int minStickers(String rest,String[] arr) {
// if(rest.equals("")) {
// return 0;
// }
// int next=0;
// for(String first:arr) {
// rest-first -> nextRest;
// int cur=minStickers(nextRest, arr);
// next=Math.min(next, cur);
// }
// return next+1;
// }
public static int minStickers1(String[] stickers,String target) {
int n=stickers.length;
int[][] map=new int[n][26];
for(int i=0; i<n; i++) {
char[] str=stickers[i].toCharArray();
for(char c:str) {
map[i][c-'a']++;
}
}
HashMap<String, Integer> dp=new HashMap<>();
dp.put("", 0);
return process1(dp, map, target);
}
// dp 傻缓存,如果rest已经算过了,直接返回dp中的值
// 0...N中每一个字符串所含字符的词频统计
// 返回值是-1,map中的贴纸无论如何都无法搞定rest
public static int process1(HashMap<String, Integer> dp,int[][] map,String rest) {
if(dp.containsKey(rest)) {
return dp.get(rest);
}
// 搞定rest,使用最少的贴纸数量
int ans=Integer.MAX_VALUE;
// n种贴纸
int n=map.length;
// tmap替代rest
int[] tmap=new int[26];
char[] target=rest.toCharArray();
for(char c:target) {
tmap[c-'a']++;
}
// map-tmap
for(int i=0; i<n; i++) {// 枚举当前第一张贴纸是谁
// 小贪心 确保贴纸中至少含有目标字符串中的一种字符才进行尝试
// 目标字符串中0位置的字符,当前贴纸是否有
if(map[i][target[0]-'a']==0) {
continue;
}
StringBuilder sb=new StringBuilder();
// i 当前来到的第一张贴纸
// j 枚举a~z字符
for(int j=0; j<26; j++) {
if(tmap[j]>0) {// j这个字符是target需要的(要搞定的字符串里有这个字符)
for(int k=0; k<Math.max(0, tmap[j]-map[i][j]); k++) {
sb.append((char)('a'+j));
}
}
}
// 经历上面的for循环后,目标字符串减去了第一张贴纸(i)里的字符,
// 剩余的字符在sb里面
String s=sb.toString();
int tmp=process1(dp, map, s);
if(tmp!=-1) {
ans=Math.min(ans, tmp+1);
}
}
dp.put(rest, ans==Integer.MAX_VALUE?-1:ans);
return dp.get(rest);
}
public static void main(String[] args) {
String[] arr= {"aaaa","bbaa","ccddd"};
String str="abcccccdddddbbbaaaaa";
System.out.println(minStickers1(arr,str));
}
}