leetcode 20.有效的括号(Java实现)

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

有效字符串需满足:

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

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


示例 1:

输入: "()"
输出: true

示例 2:

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

示例 3:

输入: "(]"
输出: false

示例 4:

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

示例 5:

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

tip:栈的典型的应用,括号的配对。

思路分析:

       首先,我们可以将两种特殊的情况直接排除,即当输入的字符串为null或长度为0时,我们可以直接返回true;当输入的字符串的长度为奇数时,则直接返回false。排除了这两种情况之后,我们可以通过栈这种数据结构来帮助我处理这个问题。我们可以从字符串的第一个字符开始逐一遍历,若为"左边"括号,则将这个字符压栈。若为"右边"括号,则判断栈是否为空,若为空,则返回false。否则将栈顶元素出栈,判断这个栈顶元素的括号是否与这个"右边"括号匹配,若匹配则继续遍历下个字符,否则则直接返回false。当所有的字符都遍历完成,栈为空,则返回true,否则说明还有括号未配对,则返回false。既然思路已经理清了。我们就可以顺着这个思路来完成代码了。


代码实现:

public static boolean isValid(String s) {
		if (s == null || s.length() == 0) { //s为空或长度为0
			return true;
		}
		if (s.length() % 2 != 0) { //s的长度为奇数
			return false;
		}
		// 构建对应关系
		Map<Character, Character> map = new HashMap<Character, Character>();
		map.put('(', ')');
		map.put('[', ']');
		map.put('{', '}');
		Stack<Character> stack = new Stack<Character>(); // 创建栈
		char[] chars = s.toCharArray(); // 获得字符串的每个字符
		if (chars[0] == ')' || chars[0] == ']' || chars[0] == '}') { // 若第一个字符为"右边"括号,则false
			return false;
		} else { // 否则将第一个压栈
			stack.push(chars[0]);
		}
		for (int i = 1; i < chars.length; i++) { // 从第二个字符开始遍历数组
			if (chars[i] == '(' || chars[i] == '[' || chars[i] == '{') { // 若字符为"左边"括号,则压栈
				stack.push(chars[i]);
			} else { // 否则对chars[i]与栈顶元素进行判断是否匹配
				if (stack.isEmpty()) { //若栈为空
					if (chars[i] == ')' || chars[i] == ']' || chars[i] == '}') {
						return false;
					} else { //为"左边"括号,则压栈
						stack.push(chars[i]);
						continue;
					}
				}
				char ch = stack.pop(); // 弹出栈顶元素
				char want = map.get(ch); // 通过map查看期待的匹配符号
				if (want != chars[i]) { // 若chars[i]不为期待符号,则false
					return false;
				}
			}
		}
		if (stack.isEmpty()) { //若最后栈为空,即所有元素都匹配成功
			return true;
		}
		else{
			return false;
		}
	}

代码优化:       

       我们第一次代码借助了栈这种数据结构来帮助我们完成,我们可以试着想想,能不能不借助栈,就能完成同样的工作呢?这当然是可以的,我们可以模仿着栈,定义一个光标cur来指向"栈顶元素"。这样我们就实现了类似于栈的结构,而并没有真正的用到栈,这样程序的执行效率就提高了不少。

public static boolean isValid(String s) {
        char[] chs=s.toCharArray();  //获取字符数组
        int cur=0;  //定义光标位置
          for(int i=0;i<s.length();i++){ //从一个字符开始
            char c=s.charAt(i);
            switch (c){
                    case '(': //若为"左边"括号,则光标向右移动一个位置
                    case '[':
                    case '{':chs[cur++]=c; break;
                      //分别对右边括号进行匹配
                    case ')':
                    	if(cur==0) //若栈为空
                    		return false;
                    	char c1=chs[--cur]; //获取"栈顶元素"
                    	if(c1!='(')
                    		return false;
                    	break;
                    case ']':
                    	if(cur==0)
                    		return false;
                    	char c2=chs[--cur];
                    	if(c2!='[')
                    		return false;
                    	break;
                    case '}':
                    	if(cur==0)
                    		return false;
                    	char c3=chs[--cur];
                    	if(c3!='{')
                    		return false;
                    	break;
            }
        }
        if(cur!=0){  //若最后光标不为0,则还有未匹配的括号
            return false;
        }
        return true;
	}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值