LeetCode0032-最长有效括号
字节二面算法题。
给你一个只包含 '('
和 ')'
的字符串,找出最长有效(格式正确且连续)括号子串的长度。
https://leetcode-cn.com/problems/longest-valid-parentheses/comments/
以下实现的是,找出有效的括号对数(输出有效括号的数目),没有实现连续
//dp[i]表示第i位上有效括号的长度 public int longestValidParentheses(String s) { if(s==null||s.length()<=0) return 0; int[] dp = new int[s.length()]; dp[0]=0; int max=0; int i=1; while(i<s.length()){ char ch= s.charAt(i); if(ch =='('){ dp[i] = dp[i-1]; }else{ if(s.charAt(i-1)=='('){ dp[i]=dp[i-1]+2; }else if(s.charAt(i-1) == ')'){ if(i-dp[i-1]-1<0){ dp[i]=dp[i-1]; } else if(s.charAt(i-dp[i-1]-1)=='('){ dp[i]=dp[i-1]+2; }else{ dp[i]=dp[i-1]; } } } max=Math.max(dp[i],max); i++; } return max; }
以下为最后结果:
重点:
理清公式:
dp[i]记录的是,以string.charAt(i)位置为结尾的,有效连续括号的长度,重点要看当前位置对于整个括号的贡献。对于"()(",dp[0]=0;dp[1]=2;dp[3]=0,因为在位置3上,“()(”根本不是一个有效括号!所以dp[3]=0
公式: 当 s[i] = '(' 时,s[i] = 0; 当s[i] = ') '时,如果 s[i-1]='(',则 dp[i] = dp[i-2]+2; (保证i-2>=0) 如果s[i-1]=')',若,i-dp[i-1]-1='(',则 dp[i] = dp[i-1] +2 + dp[i-dp[i-1]-2] (保证i-dp[i-1]-2>=0); 若 i-dp[i-1]-1不是'('或者为空,则 dpp[i]=0,表示当前位置的')'无法构成一个有效的括号。 上面公式是指:在dp[i-1]个有效括号之前(i-dp[i-1]-1),是否有一个'('可以与当前位置的右括号构成一个有效的括号,此外也需要考虑,在这个左括号之前是否已经有连续的括号(dp[i-dp[i-1]-2]的值); |
class Solution { //dp[i]表示第i位上有效括号的长度 public static int longestValidParentheses(String s) { if(s==null||s.length()<=0) return 0; int[] dp = new int[s.length()]; dp[0]=0; int max=0; int i=1; while(i<s.length()){ char ch= s.charAt(i); if(ch =='('){ dp[i] = 0; // ch == ')'时 }else{ //如果恰好左边为左括号,则+2,需要控制i-2>=0 if(s.charAt(i-1)=='('){ dp[i]= (i>=2?dp[i-2]+2:2); } //如果左边为右括号,需要判断跨过前面有效括号dp[i-1]的前一个是什么括号 else { // if(i-dp[i-1]-1<0){ // dp[i]=0; // } // else if(s.charAt(i-dp[i-1]-1)=='('){ // dp[i]=dp[i-1]+2+(i-dp[i-1]-2>=0?dp[i-dp[i-1]-2]:0); // }else{ // dp[i]=0; // } if(i-dp[i-1]-1>=0 && s.charAt(i-dp[i-1]-1)=='('){ dp[i]=dp[i-1]+2+(i-dp[i-1]-2>=0?dp[i-dp[i-1]-2]:0); }else{ dp[i]=0; } } } max=Math.max(dp[i],max); i++; } return max; } public static void main(String[] args) { String s =")()())()()("; int result =longestValidParentheses(s); System.out.println(result); } }