Generate Parentheses 【Leetcode】
来源:互联网 发布:简洁html网址导航源码 编辑:程序博客网 时间:2024/04/29 15:49
哥们存在的意义就是为了衬托神的存在,又一次体现了渣代码和神代码的区别
又是无聊记忆搜索dp,懒得写优化的key直接拿中间结果存key了。
其实我觉得这个题的关键在于如何抽象这个结果的表示形式,我只想到了用一个二维数组进行存储,
2,1
2,1
表示第一位置上两个左括号两个右括号,第二个位置上一个左一个右。[[]][]
还有一种特殊情况,就是
2,1
1,2
对应于[[][]] 注意dp内循环的顺序,右括号永远在左括号右边,防止出现
1,2
2,1
对应[]][[],显然这是个错误解
int[][] ms = new int[2][];ArrayList<String> res = new ArrayList<String>();HashMap<String, Integer> traceMap = new HashMap<String, Integer>();public String getLR(int num, int lr) {String s = "";String basic = "(";if (lr == 1)basic = ")";for (int i = 0; i < num; i++)s += basic;return s;}public String getRes(boolean save) {//String ds="";//for (int i = 0; i < ms[0].length; i++) {//if(ms[0][i]==0)//continue;//ds+=ms[0][i]+"/"+ms[1][i]+", ";//}//System.out.println(ds);String s = "";for (int i = 0; i < ms[0].length; i++) {if(ms[0][i]==0)continue;s += getLR(ms[0][i], 0) + getLR(ms[1][i], 1);}if (save)res.add(s);return s;}public void dp(int n, int currentMax) {//System.out.println("dp n="+n+" currentMax="+currentMax);String key = getRes(false);Integer v = traceMap.get(key);if (v != null)return;traceMap.put(key, 1);if (n <= 0){getRes(true);return;}for (int i = 0; i <currentMax; i++) {ms[0][i]++;for (int j = i; j <currentMax; j++) {ms[1][j]++;dp(n - 1, currentMax);ms[1][j]--;}ms[0][i]--;}ms[0][currentMax] = 1;ms[1][currentMax] = 1;dp(n - 1, currentMax + 1);ms[0][currentMax] = 0;ms[1][currentMax] = 0;}public ArrayList<String> generateParenthesis(int n) {ms[0] = new int[n + 1];ms[1] = new int[n + 1];dp(n, 0);return res;}
========================================
再看看人家的神代码
ArrayList<String> res=new ArrayList<String>();int n;public void dp(String s, int l,int r){if(l==n){//for(int i=0;i<l-r;i++)//s+=")";res.add(s);return;}dp(s+"(",l+1,r);if(l>r)dp(s+")",l,r+1);}public ArrayList<String> generateParenthesis(int N) {n=N;dp("",0,0);return res;}
中间两句我注释掉了,不注释掉就是最终结果。这个思路太秒了。其实还是dp,但是人家分析获得的状态专一方程是和渣不一样的。去掉注释运行一下看看结果就能想明白为什么这么做了。对于N,一定有N个左括号和N个有括号(废话)。
1.既然一定有n个左括号,我们就先把n个左括号画出来,一个左括号占一个数组位置,剩下的问题就是考虑每个数组单元里放几个右括号的问题了。(假设数组存在为a[]=new a[n]);
2.问题是随意排列,有错误解,因此需要定义错误解。从左往右读,遇到l则+1,遇到r则-1,sum<0则是错误解,从右往左亦然。所以半神解法就是来个全排列然后根据错误解定义删掉错误解。
注意:这个解法需要数组a[],这个方法如果求n个括号的解的个数的时候会很快,但在这个题里搞不过神DP啊
3. 最后在来看神的DP解,其实他用的就是最普通的状态转移方程,每添加一个字符就进入新的状态。正确性判断就是任何状态从左向右l>=r即可,注意L的控制由n完成。
个人感受:
感觉做DP就是多做多做突然就顿悟了,虽然人家都说边界条件,状态控制很多很多,但你自己没有真正遇到过就没有什么感受。
还有DP的关键就是分析,这个题解法很多,从我最笨的二维数组定义状态到神的单字符状态,重要的是结合题意,
1. 分析清楚,变化的是什么,是一个字符,一个单词,还是什么。找好变化量,往往能使半功倍
2. 搞清楚状态控制条件,如果变化量选的不合适,状态控制条件就会非常复杂
3. 记忆优化,渣都知道的东西就不提了
4. 没事了总想试试bottom up 从来没成过,这个题貌似也高不了吧
Reright @ 2014-1-31
ArrayList<String> reslist=new ArrayList<String>(); int[] res; int num; public void genRes(){// for(int i:res)// System.out.print(i+" ");// System.out.println(); String s=""; for(int i=1;i<res.length;i++){ s+="("; for(int j=0;j<res[i];j++) s+=")"; } reslist.add(s); } public void dp(int position,int usedright){ //System.out.println("dp "+position+" "+usedright); if(usedright>=position) return; if(position==num){ res[num]=num-usedright; genRes(); return; } for(int i=0;i<=position;i++){ res[position]=i; dp(position+1,usedright+i); } } public ArrayList<String> generateParenthesis(int n) { res=new int[n+1]; if(n==0) return reslist; num=n; dp(1,0); return reslist; }
Code Rewrite:
ArrayList<String> reslist = new ArrayList<String>();int num;public void dp(int p, int leftp, String s) {if (p == num){for(int i=1;i<=leftp;i++)s+=")";reslist.add(s);return;}String ts = "";for (int i = 0; i <= leftp; i++) {dp(p + 1, leftp + 1 - i, s + ts+ "(" );ts += ")";}}public ArrayList<String> generateParenthesis(int n) {num = n;dp(0, 0, "");return reslist;}
- LeetCode: Generate Parentheses
- LeetCode: Generate Parentheses
- [Leetcode] Generate Parentheses
- leetcode 51: Generate Parentheses
- [LeetCode] Generate Parentheses
- Leetcode: Generate Parentheses
- LeetCode Generate Parentheses
- 【leetcode】Generate Parentheses
- [LeetCode]Generate Parentheses
- Leetcode Generate Parentheses
- LeetCode-Generate Parentheses
- LeetCode: Generate Parentheses
- LeetCode - Generate Parentheses
- LeetCode 22: Generate Parentheses
- LeetCode: Generate Parentheses
- Leetcode: Generate Parentheses
- 【leetcode】Generate Parentheses
- Leetcode: Generate Parentheses
- js查找某元素中的所有图片地址
- .net文件上传,客户端用jquery file upload
- TextView android:drawablePadding 不起作用
- [LeetCode]128.Longest Consecutive Sequence
- MemcachedClient
- Generate Parentheses 【Leetcode】
- QTP添加新的action中之对象库的关联
- Java SE 6 新特性系列
- 自定义preference onBindView易犯的错误
- 【其他】Windows Media Services 无法启动
- Ubuntu装好后因为“初始化月份字符串出错”无法启动libreoffice --中文版本
- configure: error: Subversion requires SQLite,Linux安装Subversion的各类问题
- Get apk file information with aapt tool
- linux 禁用selinux