一)电话号码的字母组合
17. 电话号码的字母组合 - 力扣(LeetCode)
1)画出决策树:只是需要对最终的决策树做一个深度优先遍历
把图画出来,知道每一层在干什么,代码就能写出来了
2)定义全局变量:
1)定义一个哈希表来处理数字和字符串的映射关系
2)使用ret来保存最终结果
class Solution { HashMap<Character,String> result=new HashMap<>(); List<String> ret; StringBuilder path; public List<String> letterCombinations(String digits) { this.path=new StringBuilder(); result.put('2',"abc"); result.put('3', "def"); result.put('4', "ghi"); result.put('5', "jkl"); result.put('6', "mno"); result.put('7', "pqrs"); result.put('8', "tuv"); result.put('9', "wxyz"); this.ret=new ArrayList<>(); if(digits.length()==0){ return ret; } dfs(result,digits,0); return ret; } public void dfs(HashMap<Character,String> result,String digits,int index){ if(index==digits.length()){ //这个最终条件,第一次就写错了,index遍历到数组的最后一个位置 ret.add(path.toString()); return; } Character number=digits.charAt(index); String string=result.get(number); char[] chars=string.toCharArray(); for(int i=0;i<chars.length;i++){ path.append(chars[i]); //继续遍历到下一层 dfs(result,digits,index+1); //恢复现场,回退到上一层 path.deleteCharAt(path.length()-1); } } }
二)括号生成:
22. 括号生成 - 力扣(LeetCode)
先进行想一下,什么是有效的括号组合?
1)左括号的数量==有括号的数量
2)从头开始的任意一个子串中,左括号的数量都是大于等于右括号的数量,如果发现右括号的数量是大于左括号的,那么必然会出现一个右括号没有做括号匹配,所以就不是一个有效的括号组合
假设如果n==3,那么我们只是需要枚举6个位置即可,因为n==3表示的是三对括号,一共有6个位置,那么我们只是需要进行暴力枚举6个位置可能出现的情况就可以了
一)画出决策树:
二)定义一个全局变量:
1)left表示左括号的数量,right表示右括号的数量,N表示一共有多少对括号
2)当进行深度优先遍历的时候,使用这个path变量来进行记录这个路径中曾经出现过的括号
三)dfs所干的事:
当左括号合法的时候,把左括号添加到path中当右括号合法的时候,把右括号添加到path中
四)递归:遇到叶子节点的时候,将这个path添加到ret中,遇到叶子节点的情况就是当right==N的时候,说明此时右括号已经满了
class Solution { int N; StringBuilder path; List<String> ret; int right=0; int left=0; public List<String> generateParenthesis(int n) { N=n; path=new StringBuilder(); ret=new ArrayList<>(); dfs(); return ret; } public void dfs(){ if(right==N){ ret.add(path.toString()); return; } //选择左括号 if(left<N){ path.append('('); left++; dfs(); //回溯恢复现场 left--; path.deleteCharAt(path.length()-1); } if(right<left){ path.append(')'); right++; dfs(); //回溯恢复现场 right--; path.deleteCharAt(path.length()-1); } } }
其实本质上来说把刚才的那些全局变量放到参数里面,只是回溯时候的操作是不一样的
三)组合:
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
1)实现剪枝的操作:当我们进行枚举当前数的时候,只需要从当前数的下一个数字开始进行枚举就可以了,只需要控制dfs的参数即可
2)dfs做的事:从pos位置开始进行枚举,将枚举的情况添加到path中即可
3)回溯:当枚举完成当前位置向上归的过程中,先把path中添加的数进行剔除,然后再返回到上一层即可
4)递归出口:k==path.size()
class Solution { List<List<Integer>> ret; List<Integer> path; int N; int k; public List<List<Integer>> combine(int n, int k) { N=n; this.k=k; path=new ArrayList<>(); ret=new ArrayList<>(); dfs(1); return ret; } public void dfs(int index){ if(path.size()==k) { ret.add(new ArrayList<>(path)); return; } for(int i=index;i<=N;i++){ path.add(i); dfs(i+1); path.remove(path.size()-1); } } }
四)目标和
494. 目标和 - 力扣(LeetCode)
1)