Java&LeetCode 初入门——020. 有效的括号

  • 题目
  • 个人解法
  • 官方解法
  • 方法
  • 算法



文内代码全部采用JAVA语言。


个人认为本文的办法虽然慢,但是非常好理解,是小白们的福音。

题目

给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。左括号必须以正确的顺序闭合。

注意空字符串可被认为是有效字符串。

测试用例

示例 1:

输入: "()"
输出: true

示例 2:

输入: "()[]{}"
输出: true

示例 3:

输入: "(]"
输出: false

示例 4:

输入: "([)]"
输出: false

示例 5:

输入: "{[]}"
输出: true

个人解法

看到这个题目的时候,没有一下子想到解决办法,因为需要考虑的情况实在太多了。但是在研究了测试用例之后,不难发现,不论多么复杂的情况,如果是有效的括号,那么总有两个成套的括号是挨在一起的,也就是总存在"()","[]","{}“的子字符串,我们如果将成套的括号一遍一遍的删除,最终变成了”"空字符串的话,说明是有效的 ,反之无效。

但是傻瓜办法总是有点缺陷,就是时间很长。执行用时: 192 ms, 在Valid Parentheses的Java提交中击败了1.40% 的用户。几乎垫底。但代码简单,通俗易懂,是小白们的福音了。

class Solution {
    public boolean isValid(String s) {
		while(s.indexOf("()")!=-1||s.indexOf("[]")!=-1||s.indexOf("{}")!=-1) {
		//如果字符串里存在"()","[]","{}",那么就删去。
			s=s.replace("()", "");
			s=s.replace("[]", "");
			s=s.replace("{}", "");
		}
		//全部能全部删除,说明有效。
		if (s.length()==0) {
			return true;
		}
		else {
			return false;
		}
	}
}

这么垃圾的算法如果用于编译器那估计会慢到使用者想砸电脑,还是学习一下官方解法吧。

官方解法

方法

关于有效括号表达式的一个有趣属性是有效表达式的子表达式也应该是有效表达式。(不是每个子表达式)例如

java编程数学运算括号校验 java 有效的括号_有效的括号

此外,如果仔细查看上述结构,颜色标识的单元格将标记开闭的括号对。整个表达式是有效的,而它的子表达式本身也是有效的。这为问题提供了一种递归结构。例如,考虑上图中两个绿色括号内的表达式。开括号位于索引 1,相应闭括号位于索引 6。

利用栈的功能,实现括号的消除,避免了循环查找。

算法

  1. 初始化栈 S。
  2. 一次处理表达式的每个括号。
  3. 如果遇到开括号,我们只需将其推到栈上即可。这意味着我们将稍后处理它,让我们简单地转到前面的 子表达式。
  4. 如果我们遇到一个闭括号,那么我们检查栈顶的元素。如果栈顶的元素是一个 相同类型的
    左括号,那么我们将它从栈中弹出并继续处理。否则,这意味着表达式无效。
  5. 如果到最后我们剩下的栈中仍然有元素,那么这意味着表达式无效。
class Solution {

  // Hash table that takes care of the mappings.
  private HashMap<Character, Character> mappings;

  // Initialize hash map with mappings. This simply makes the code easier to read.
  public Solution() {
    this.mappings = new HashMap<Character, Character>();
    this.mappings.put(')', '(');
    this.mappings.put('}', '{');
    this.mappings.put(']', '[');
  }

  public boolean isValid(String s) {

    // Initialize a stack to be used in the algorithm.
    Stack<Character> stack = new Stack<Character>();

    for (int i = 0; i < s.length(); i++) {
      char c = s.charAt(i);

      // If the current character is a closing bracket.
      if (this.mappings.containsKey(c)) {

        // Get the top element of the stack. If the stack is empty, set a dummy value of '#'
        char topElement = stack.empty() ? '#' : stack.pop();

        // If the mapping for this bracket doesn't match the stack's top element, return false.
        if (topElement != this.mappings.get(c)) {
          return false;
        }
      } else {
        // If it was an opening bracket, push to the stack.
        stack.push(c);
      }
    }

    // If the stack still contains elements, then it is an invalid expression.
    return stack.isEmpty();
  }
}

用上了栈之后果然快了很多。
附上自己写的用栈的JAVA代码, 以及可以用于测试的主程序。

public boolean isValid2(String s) {
		Map<Character, Character> map1=new HashMap<Character, Character>();
		map1.put(')','(');
		map1.put(']','[');
		map1.put('}','{');
		
		Stack<Character> st=new Stack<>();

		
		for (int i = 0; i < s.length(); i++) {
			char c =s.charAt(i);
			
			if (map1.containsKey(c)) {
				if(st.empty()==true || st.peek()!=map1.get(c)) {
					return false;	
				}
				else {
					st.pop();
				}
			}
			else {
				st.push(c);
			}
			
		}
		return st.empty();
	}
	public static void main(String[] args) {
		leedcode020 l20=new leedcode020();
		System.out.println(l20.isValid2("({})"));
	}