DFS-分礼物(华为笔试)+括号生成(LeetCode 22)
DFS解决此类问题的思路是用二叉树枚举并确定剪枝和结束的条件。
(1)分礼物
题目描述:k个小朋友分n个礼物,问有多少种分法。
示例:
输入:k=2,n=3
输出:4
|***
*|**
**|*
***|
思路:(图如下)相当于在4个空格里面填符号,每个位置上要么有礼物( * ),要么没礼物( | ),用二叉树进行枚举,按深度优先搜索进行遍历,在枚举过程中发现剪枝条件以及结束的条件:
剪枝条件:k = 0;此时意味着每个人都不再得到礼物,不管是否还剩余礼物,这种情况都将剔除;
结束条件:理论上当 n = 0时即结束,但是注意到,当(2,0)时若结束输出 *** ,少了一个 | ,此时应当继续进行到(1,0)才应是正确结果;
总结:k = 1 且 n = 0 为结束条件;
代码如下(考虑了输入输出):注意DFS方法的格式大多按照此格式书写即可
import java.util.ArrayList; import java.util.List; import java.util.Scanner; public class dfsExam { static Scanner sc = new Scanner(System.in); public static void main(String[] args) { int k = sc.nextInt(); int n = sc.nextInt(); List<String> res = new ArrayList<>(); dfs(k,n,"",res); System.out.println(res.size()); for(String s : res){ System.out.println(s); } } public static void dfs(int k, int n, String s, List<String> res) { if (k == 0 ) { return; } if (n+k==1){ res.add(s); return; } if (k > 0) { dfs(k - 1, n, s + "|", res); } if (n > 0) { dfs(k, n - 1, s + "*", res); } } }
(2)括号生成器
题目描述:数字 n
代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
示例:
输入:n = 3 输出:["((()))","(()())","(())()","()(())","()()()"]
思路:(left,right)进行二叉树图解,类似分礼物分析其剪枝条件和结束条件;
剪枝条件:当left<right时需要剔除
结束条件:当left = 0 且 right = 0 时结束;
代码如下:
class Solution { public List<String> generateParenthesis(int n) { List<String> res = new ArrayList<String>(); if (n<=0) { return null; } dfs("",res,n,n); return res; } public void dfs(String s, List<String> res, int left, int right){ if (left == 0 && right == 0) { res.add(s); return; } if(left > right) { return; } if (left >0) { dfs(s + "(", res, left -1, right ); } if(right > 0) { dfs(s + ")", res, left, right -1); } } }
要掌握这种dfs的分析思路和代码结构!熟能生巧!