在Java中,我们可以按照相同的动态规划思路来解决这个问题。以下是使用Java实现的代码:
java复制代码 public class LongestValidParentheses { public int longestValidParentheses(String s) { int maxLength = 0; int[] dp = new int[s.length()]; Deque<Integer> stack = new ArrayDeque<>(); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (c == '(') { stack.push(i); } else { if (!stack.isEmpty()) { int startIndex = stack.pop(); int length = i - startIndex + 1; if (startIndex > 0) { length += dp[startIndex - 1]; } dp[i] = length; maxLength = Math.max(maxLength, dp[i]); } } } // 遍历dp数组,查找最长有效子串 for (int len : dp) { maxLength = Math.max(maxLength, len); } return maxLength; } public static void main(String[] args) { LongestValidParentheses solution = new LongestValidParentheses(); String s = "(()"; System.out.println(solution.longestValidParentheses(s)); // 输出 2 } }
在这个Java实现中,我们使用了一个Deque(双端队列)作为栈来存储左括号的索引。当遇到右括号时,我们检查栈是否为空,如果不为空,则弹出栈顶元素(即左括号的索引),并计算当前有效子串的长度。我们还维护了一个dp数组来记录以每个位置结尾的最长有效括号子串的长度。最后,我们遍历整个dp数组来找到最长的有效子串长度。
注意,这个实现中并没有显式地处理栈为空的情况,因为当栈为空时,意味着没有左括号可以匹配当前的右括号,所以dp[i]仍然是0,无需特别处理。此外,在遍历dp数组查找最长有效子串时,我们可以在第一次遍历字符串时就更新maxLength,这样就可以避免第二次遍历dp数组,从而稍微优化性能。上面的代码中保留了第二次遍历,是为了保持逻辑清晰。在实际应用中,可以根据需要去掉这部分代码。