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)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章