FTPrep, 77 Combinations
来源:互联网 发布:淘宝网精品推荐棉拖鞋 编辑:程序博客网 时间:2024/06/05 22:30
这是一大类型的题,对比总结发现就知道:核心是:backtracking的core,应对不同变体的处理方式是:退出条件的设立。
还有一个特点就是他的输出是 list in list 的格式,首先要得到一个关于combination的list,然后在一定判断条件下,把这个valid的list加入结果result中。
TODO:
backtracking就是DFS的一种特例,是走到根节点,这个根节点可以作为结束条件,比如 电话号码,和 generate parens 那道题,当然也可以在中间进行结束,只要配置相应的判断条件就够了。
突然我就有个问题,为什么电话号码和generate parens 那道题,没有backtracking的步骤,照理说,也是同样的DFS过程,都是一直走到树的最左侧那条分支,即从左到右方向的第一个根节点,然后向上回溯,向下继续寻找第二个根节点。依次进行下去。 对比观察,终于发现关键所在。
1. telephone number 和 generate parens 那里的item是string,result的形式是一个list。 而combination的item本身就是一个list,最终结果是 list in list。这第一点是表面上区别,但是也蛮重要,因为item类型不同,其实就意味着 形成的过程/怎么generate item 有所差异。
2, 在DFS中,string的处理是直接在interface的参数列表里进行处理的,因为可以非常方便的通过 str1+“a” 来产生新的对像,所以每一个分支时,item都一个新的对象。相反的,在backtracking中,对item添加元素都在是for() loop里,进行操作,然后把item pass 到interface 的参数列表里,所以这个item 自始至终是一个对象,所以在backtracking 回溯的时候要remove 这个 iteration中加进去的元素,进入到 for() loop 的下一个 iteration中去。
3, 这一点其实是最大的不同,最明显的区别!在MU吃完pizza散步的时候突然意识到这才最本质的区别。在DFS中,是通过index来 逐层 深入的!for() loop是要遍历“该层”的所有分支!!这个分支可以是很多个。而在backtracking的题目里,for() loop 有两个意思:1,把每个元素都作为一个起点,即数的根节点(在第一个for() loop 里遍历元素时)这一点是最本质的,因为第2点是基于第1点的;2,就是遍历每一层(在递归进入下一层时,下一层内部的for loop() ,因为这个interface里已经带有一个上一层的item了)!!那么他的分支是什么呢?又是怎么实现的??分支只有2种,选和不选,其实只有选才有意义,所以在每一层,只有一个操作,就是item.add(xxx),然后就继续到下一层了。进入下一层的interface,什么都没有变,只有item变了 和 层数(更准确的说是树的起始点)变了!!从图形化的角度来说,combination的图形化,是把每个元素都可以看成是一个树的根节点,也就是起始位置,因此可以形成N棵树(每棵树的大小逐渐变小,一开始是4个元素的数,然后是3,然后2,1:[1,2,3,4], [1,2,3], [2,3,4], [3,4,1], [4,1,2], [1,2], []...)以各个元素作为根节点往下延伸的时候,仍然需要递归调用。
对比一下,DFS中 往下一层进入时的interface,变化的值有:层数(仅仅是层数,没有起点,因为这里只有一个棵树一个起点一个根节点)即index,和item(item是直接在interface里生成的,不需要 变量 来维护)。
所以从interface的变化来说还是很类似的,interface里都有控制层数的参数变化,DFS的层数是通过index来控制,BT的层数是通过start来控制。同时没进入下一轮的interface所带的item都是上一轮形成的item,DFS在interface里直接形成,是new variable,BT是调用原来的item,同一个variable,只是其中的元素+1 !但是for() loop的作用上,完全不是一回事。DFS的for是分支for,BT的for是起点for,BT其实没有分支(只有选择才有意义)。
唉,在发现这个对比之前,碰到了两者之间对比和疑问,是有点烦的,因为这两类题目都做了不少了,但还是有些困惑,现在对比发现了其中要义,还是蛮爽的。
先上代码,其实这个代码中可以总结出 backtracking的一类模版解法,<--- TODO
class Solution { public List<List<Integer>> combine(int n, int k) { List<List<Integer>> result = new ArrayList<>(); if(n<=0 || k>n) return result; List<Integer> item = new ArrayList<>(); combination(n, k, result, item, 1); return result; } private void combination(int n, int k, List<List<Integer>> result, List<Integer> item, int start ){ // if(start>n-k+1) return; // question: why this is not right?? if(item.size()==k){ result.add(new ArrayList<Integer>(item)); return; } for(int i=start; i<=n; i++){ // bug: i<=n+1-k; item.add(i); combination(n, k, result, item, i+1); // here I always made the mistake by: combination(n, k, result, item, start+1); item.remove(item.size()-1); } }}// combination type of question, the core is the for() loop for backtracking, special case of DFS!!!// variants and corresponding solutions are in: 1, the checking condition!!! 2, the presentation of the selection pool, which can be array, or here is just a range from 1 to n, [1, n]
Leetcode 讨论区有一个很不错的,关于permutation,combination的各种变体的模版,非常值得参考,因为都是backtracking core + conditioning !!! I like this short summary, core + conditioning.
phone number 点击打开链接的代码:
public class Solution { public List<String> letterCombinations(String digits) { List<String> list = new ArrayList<String>(); if(digits.length()==0) return list; HashMap<Character, String> table=new HashMap<>(); table.put('2',"abc"); table.put('3',"def"); table.put('4',"ghi"); table.put('5',"jkl"); table.put('6',"mno"); table.put('7',"pqrs"); table.put('8',"tuv"); table.put('9',"wxyz"); table.put('0',"abc"); table.put('1',""); branch(digits, table, 0, list, ""); return list; } private void branch(String digits, HashMap<Character, String> table, int index, List<String> list, String item){ if(index==digits.length()) { list.add(item); return; } else{ String str= table.get(digits.charAt(index)); for(int i=0; i<str.length(); ++i){ branch(digits, table, index+1, list, item+str.charAt(i)); } } } }
其实这里的for loop里的str应该改名叫做 branches,这才是真正含义,然后helper function应该叫做dfs
class Solution { public List<String> letterCombinations(String digits) { List<String> result = new ArrayList<String>(); if(digits.length()==0) return result; HashMap<Character, String> table=new HashMap<>(); table.put('2',"abc"); table.put('3',"def"); table.put('4',"ghi"); table.put('5',"jkl"); table.put('6',"mno"); table.put('7',"pqrs"); table.put('8',"tuv"); table.put('9',"wxyz"); table.put('0',"abc"); table.put('1',""); dfs(digits, table, result, "", 0); return result; } private void dfs(String digits, HashMap<Character, String> table, List<String> result, String item, int index){ if(index==digits.length()){ result.add(item); return; } String branches = table.get(digits.charAt(index)); for(int i=0; i<branches.length(); i++){ dfs(digits, table, result, item+branches.charAt(i), index+1); } }}
- FTPrep, 77 Combinations
- 77Combinations
- [77]Combinations
- LeetCode 77 Combinations
- [leetcode 77] Combinations
- Leetcode NO.77 Combinations
- [leetcode] 77 Combinations
- [LeetCode 77]Combinations
- leetcode || 77、Combinations
- leetcode-77 Combinations
- LeetCode-77 Combinations(组合)
- Combinations - LeetCode 77
- leetcode 77:Combinations
- LeetCode(77) Combinations
- Leetcode #77 Combinations
- [leetcode-77]Combinations(java)
- leetcode 77: Combinations
- LeetCode(77) Combinations
- deepin15.4.1安装caffe
- 30天自制操作系统-第1天心得笔记
- PHP字符集转换问题
- HandlerThread源码分析
- c# 双缓冲 技术与例子
- FTPrep, 77 Combinations
- java重写equals(Object obj)与重写hashCode()之间的关系
- OSMMUI.msi ErrorCode: 1603(0x643)
- Android TextView水平跑马灯
- 170919 网络-ARP欺骗原理及实现
- [Leetcode] 11, 120, 132
- 一款手机看电脑上电影视频的win10应用
- 20170920学习笔记Selenium 2 第二章测试环境搭建
- 【一分钟了解UWP】微信UWP