20200307:最长有效括号(leetcode32)

题目

在这里插入图片描述

思路与算法

  • 其实这几天不是偷懒断了写,是每天复习一阵子累的慌,挑简单的做了几个,属实没什么需要记录的,都是很简单的暴力,比如35:插入搜索位置,比如1365. 有多少小于当前数字的数字

  • 本题思路一上来想到的是栈,这类1对1的题,就是栈,碰见左括号入栈,碰见右括号出栈,最后要是栈不为空,就说明无效字符串,栈为空,则都匹配了,有效字符串,然后记得更新res结果就行。最后注意特殊情况的处理。

  • 思路二:动态规划,这类题的规律比较难找,我们看给的这俩示例:
    在这里插入图片描述
    这两个示例说:已经匹配完成的,如果后面再跟一个(),那么还是匹配的
    回头我们再看一个实例:
    ()()(())
    你发现这个字符串也是匹配的,把前面的俩()()去掉,后面的(())也是匹配的。也就是说,如果遇到这样的双括号套环,甚至三四个括号套环,也是完全可以的。因此我们需要来找出这其中的状态方程。
    思路总结:

  • 只有一个()括号时:dp[i] = dp[i-2] + 2;
    -碰到右括号套环时:先找内层括号对应的左括号的索引,

  • 则dp[i] = dp[i-1] + 2 + dp[i - 1 - dp[i-1] - 1]。

  • 思路三

  • 左右数左括号和右括号的数量,从左往右数一遍,从右往左再数一遍,更新条件:左->右时:右括号>左括号数量时,清零。同理,右->左时,右括号<左括号数量时,清零。

代码实现

思路一:

package com.immunize.leetcode.longestValidParentheses;

import java.util.Stack;

public class Solution2 {
	public int longestValidParentheses(String s) {
		// 特殊情况处理
		if (s == null) {
			return 0;
		}

		// 定义使用的变量
		int res = 0;
		// 遍历所有字符串,进行暴力,并挨个判断是否为有效括号,注意括号是成对出现的,因此注意遍历技巧
		for (int i = 0; i < s.length(); i++) {
			for (int j = i + 2; j <= s.length(); j++) {
				if (isValid(s.substring(i, j))) {
					res = Math.max(res, j - i);
				}
			}
		}
		return res;
	}

	// 判断该字符串是否有效
	private static boolean isValid(String s) {
		// 特殊情况处理

		/*
		 * 碰到左括号,则入栈一个左括号,碰到一个右括号,则出栈一个左括号,结束时如果栈空,则该字符串 是有效的,若栈不为空,则无效,
		 */
		Stack<Character> stack = new Stack<>();
		for (int i = 0; i < s.length(); i++) {
			if (s.charAt(i) == '(') {
				stack.push('(');
			} else if (!stack.empty() && s.charAt(i) == ')') {
				stack.pop();
			} else {
				return false;
			}
		}
		return stack.empty();
	}
}

思路二:

package com.immunize.leetcode.longestValidParentheses;

/**
 * ")()())"
 * 
 * 只有一个右括号时:dp[i] = dp[i-2] + 2;
 * 
 * 两个右括号时:先找内层括号对应的左括号的索引,
 * 
 * 假设两个右括号的索引为 i-1,i。则dp[i] = dp[i-1] + 2 + dp[i - 1 - dp[i-1] - 1]
 * 
 * @author Mr IMMUNIZE
 *
 */
public class Solution {
	public int longestValidParentheses(String s) {
		int maxans = 0;
		int dp[] = new int[s.length()];
		for (int i = 1; i < s.length(); i++) {
			if (s.charAt(i) == ')') {
				if (s.charAt(i - 1) == '(') {
					dp[i] = (i >= 2 ? dp[i - 2] : 0) + 2;
				} else if (i - dp[i - 1] > 0 && s.charAt(i - dp[i - 1] - 1) == '(') {
					dp[i] = dp[i - 1] + ((i - dp[i - 1]) >= 2 ? dp[i - dp[i - 1] - 2] : 0) + 2;
				}
				maxans = Math.max(maxans, dp[i]);
			}
		}
		return maxans;
	}
}

思路三:

package com.immunize.leetcode.longestValidParentheses;

public class Solution3 {
	public int longestValidParentheses(String s) {
		int res = 0;
		int left, right;
		left = right = 0;
		for (int i = 0; i < s.length(); i++) {
			if (s.charAt(i) == '(') {
				left++;
			} else {
				right++;
			}
			if (left < right) {
				left = right = 0;
			}
			if (left == right) {
				res = Math.max(res, left + right);
			}
		}

		left = right = 0;
		for (int i = s.length() - 1; i >= 0; i--) {
			if (s.charAt(i) == '(') {
				left++;
			} else {
				right++;
			}
			if (left > right) {
				left = right = 0;
			}
			if (left == right) {
				res = Math.max(res, left + right);
			}
		}
		return res;
	}
}

复杂度分析


思路时间复杂度空间复杂度
O(N²)O(N)
O(N)O(N)
O(N)O(1)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IMMUNIZE

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值