題目 https://leetcode-cn.com/problems/zuma-game/
这题根据题目我们可知,就是消去连着的球,然后剩下的球再就是一样的处理,最后消完后再去比较最小值
这是一道DFS题目,为什么用DFS呢? 因为我们可以去遍历board字符串,去看下哪些球缺多少个相同的球,然后再用我们手里的球去填充。
至于手里的球hand,我们可以用Map去存下每种球有多少个。
对于这道题来说,我们不能像游戏那样,把中间球消除后,左右两边合起来刚好又消掉。对于这样的情况,可能不是最优解。例如下图:
图中只列举几种情况。
如我们所看,对于前面那种消去WW之后,剩余RRRRBBRR,我们这时
消去前面的RRRR就不能消去全部的了。
但是我们像后面的那种,消去后面的BB,剩下RRWWRRRR,因为每次消去后,都是从前面开始遍历的,所以后面的还不会合并,因此这种成为最优解
class Solution {
Map<Character,Integer> map;
int res=10; //手上的球最多5个,所以设定为10
public int findMinStep(String board, String hand) {
if(hand==null||hand.length()==0) return -1;
map=new HashMap();
for(char c:hand.toCharArray())
map.put(c,1+map.getOrDefault(c,0));
dfs(board,0);
return res==10?-1:res;
}
void dfs(String board,int sum){
if(board.equals("")) res=Math.min(res,sum);
int n=board.length();
int i=0,j=0;
while(i<n){
char c=board.charAt(i);
j=i+1;
while(j<n&&board.charAt(i)==board.charAt(j))
j++;
int num=j-i;
//不能消掉的球
if(num<3){
Integer cnt=map.get(c);
//需要的球数量
int need=3-num;
if(cnt!=null&&cnt>=need){
String str=board.substring(0,i)+board.substring(j);
map.put(c,cnt-need);
dfs(str,sum+need);
map.put(c,map.get(c)+need);
}
}
//可以消去
else{
dfs(board.substring(0,i)+board.substring(j),sum);
}
//往后遍历
i=j;
}
}
}
主要知道怎么往下走,条件是什么,而且这类题跟回溯一样,深搜下去,回来的时候要状态回转。
简单的模板:
class Solution {
public List<List<Integer>> permute(int[] nums) {
dfs();
return ans;
}
dfs(){
//终止条件
if() ....;
//按顺序访问分支点
{
//本节点处理
//进入下一节点
//回溯,状态重置(具体情况,有些需要,有些不需要)
}
}
}