算法_01

来源:互联网 发布:清洁面膜有必要吗 知乎 编辑:程序博客网 时间:2024/06/07 21:46

1、已知一个字符串都是由左括号(和右括号)组成,判断该字符串是否是有效的括号组合,返回最长有效括号子串的长度。
例子:
有效的括号组合:()(),(()),(()())
无效的括号组合:(,()),((),()(()

package day7_19;/** * Created by 朱博文 on 2017/7/19. * 1、已知一个字符串都是由左括号(和右括号)组成,判断该字符串是否是有效的括号组合。 * 例子: * 有效的括号组合:()(),(()),(()()) * 无效的括号组合:(,()),((),()(() */public class Demo_01 {    public static boolean isValid(String str) {        if (str == null || str.equals("")) {            //如果是空字符串或者null直接返回false            return false;        }        char[] chas = str.toCharArray();                //把一个字符串转换成一组数组        int status = 0;                                 //设置状态为0        for (int i = 0; i < chas.length; i++) {         //遍历这个数组            if (chas[i] != ')' && chas[i] != '(') {     //如果这个数组不是左括号或者右括号直接返回false                return false;            }            if (chas[i] == ')' && --status < 0) {       //如果是右括号但是状态小于0也直接返回false,因为匹配一定要是status=0                return false;            }            if (chas[i] == '(') {                       //匹配左括号状态加1                status++;            }        }        return status == 0;    }    public static int maxLength(String str) {        if (str == null || str.equals("")) {            //如果是空字符串或者null直接返回false            return 0;        }        char[] chas = str.toCharArray();                //转换为数组        int[] dp = new int[chas.length];                //设置一个备忘录,长度为数组的长度。        int pre = 0;        int res = 0;        for (int i = 1; i < chas.length; i++) {         //遍历这个数组,从1开始到chas.length-1结束            if (chas[i] == ')') {                       //如果这个符号是')'则进入循环                pre = i - dp[i - 1] - 1;                //找到前面一个匹配为()或(())等的位置 这段字符串的长度的开始位置 = 前一个字符的位置-去匹配完成的长度                if (pre >= 0 && chas[pre] == '(') {     //如果前一个字符的长度大于等0并且前一个字符为'('进入循环                    dp[i] = dp[i - 1] + 2 + (pre > 0 ? dp[pre - 1] : 0);//则当前位置的dp[i]长度为前一个位置的长度+2,并且加上前一个字符的长度(如果per开始位置大于0就+前一段字符串的长度,如果不大于0就加上0)                }                                       //前一段字符串的长度            }            //0123456789AB            //((())())            //00024068            //(())(()(()))            //0024002002612            //            res = Math.max(res, dp[i]);        }        for(int x = 0 ; x < dp.length; x++)            System.out.print(dp[x]);        System.out.println();        return res;    }    public static void main(String[] args) {        String str1 = "((())())";        System.out.println(isValid(str1));        System.out.println(maxLength(str1));        String str2 = "(())(()(()))";        System.out.println(isValid(str2));        System.out.println(maxLength(str2));        String str3 = "()(()()(";        System.out.println(isValid(str3));        System.out.println(maxLength(str3));    }}

总结:

    动态转移方程:dp[i] = dp[i - 1] + 2 + (pre > 0 ? dp[pre - 1] : 0);    isValid()方法主要是设置了status状态这一变量能够快速的匹配出这个段字符串是否符形式。    maxLength(String str)方法利用了动态规划的思想,设置了一个备忘录记录了当前位置的最大字符串的长度,匹配一个')'字符,那么长度必定是+2,因为'('不会进入循环,匹配到')'可以直接+2。同时这道题最关键的点是pre变量,记录了这段子串开始的位置,然后通过dp[pre-1]加上前一段字符串的长度,有人可能会问加入再多一个子串怎么办呢? dp[i] = dp[i - 1] + 2 + (pre > 0 ? dp[pre - 1] : 0);已经记录了当前最大的长度,所以再多多少串都是一样的。
原创粉丝点击