PHP 如何验证字符串中左右括号是否匹配

3 篇文章 0 订阅

PHP笔试题,一个字符串里有很多个小括号,要求 小括号可以嵌套,但是必须保证左右匹配, 要求写出一个方法能验证该字符串中是否符合小括号规定的格式

<?php

/**
 * PHP笔试题,一个字符串里有很多个小括号,要求 小括号可以嵌套,但是必须保证左右匹配
 * 给出一个方法,要求能验证该字符串中是否符合小括号规定的格式
 */

$input1 = '))))((((()';
$input2 = '((()))()';
$input3 = '((())())';
$input4 = ')(()()()()()';

/**
//首先将该字符串分解成数组,相当于该数组全部压入到栈里
//做出栈操作,即:从右往左一个一个地弹出元素,看能否找到匹配的左括号
    1.当前是右括号,
        如果再弹出一个是左括号,则没有问题
        如果再弹出一个右括号,则要继续弹出所有左括号,记录右括号的个数,
        弹出左括号的过程中如果出现右括号个数为负数的情况,则表示左括号在右括号的右边,也属于非法字符串
        然后弹出相同个数的元素,要保证都是左括号才行。

    2、如果第一个是左括号,则表示不是合法的格式
 */


/**
 * 检验给定的字符串是否符合格式
 * @param $input 输入的字符串
 * @return bool
 */
function checkIsValid($input)
{
    $arrStack = str_split($input, 1);
    $countLeft = substr_count($input, '(');
    $numOfLeft = 0;
    $numOfRight = 0;
    if ($curr = array_pop($arrStack)) {
        if ($curr == '(' && $numOfRight == 0) { //表示最后一个字符是左括号,不合法
            return false;

        } elseif ($curr == ')') {
            ++ $numOfRight;//右括号的个数

            while (true) {
                $prev = array_pop($arrStack);
                if ($prev == '(') {
                    --$numOfRight;//遇到左括号则右括号个数减1
                    ++$numOfLeft;
                    if ($numOfRight<0) {
                        return false;
                    }
                    if ($numOfLeft == $countLeft) {
                        break;
                    }
                } elseif (is_null($prev)) {
                    if ($numOfRight === 0) {
                        return true;
                    }
                    return false;
                } elseif ($prev == ')') {
                    ++ $numOfRight;
                }
            }
//            echo "numOfRight:{$numOfRight} <br/>";
            for ($i=0; $i<$numOfRight; ++$i) {
                $prev = array_pop($arrStack);
                if ($prev != '(') {
                    return false;
                }
            }
        } elseif ($numOfRight !== 0) {    //没有元素了
            return false;
        }
    }
    return  true;
}

$result = checkIsValid($input1);
echo "input1 is valid:".var_export($result, true)."<br/>";
$result = checkIsValid($input2);
echo "input2 is valid:".var_export($result, true)."<br/>";
$result = checkIsValid($input3);
echo "input3 is valid:".var_export($result, true)."<br/>";
$result = checkIsValid($input4);
echo "input4 is valid:".var_export($result, true)."<br/>";

最终结果:
input1 is valid:false
input2 is valid:true
input3 is valid:true
input4 is valid:false

思路有点跑偏了,没抓住重点:
首先判断依据搞的太复杂了,简单一点来说就是:
仅把左括号压入栈中,遍历时碰到右括号就弹出栈中元素,由于栈中元素是LIFO(即:后进先出),自然最后一个左括号,应该对应右括号。

最终如果所有的左括号都能找到匹配的右括号,(即栈中左括号全部出栈即可断定,左右括号个数肯定相同而且也能匹配,因为栈中全部是左括号,先左括号后右括号的顺序是没有问题的) 数量匹配、顺序也没有问题,自然是合法的小括号计算表达式了。

下面给出简单的算法:

/**
 * 判断一个字符串表达式中的括号是否合法
 * @param  string  $input 
 * @return boolean        [description]
 */
function isValid($input) {
    $length = strlen($input);
    $arrStack = [];

    for ($i=0; $i<$length; ++$i) {
            if ($input[$i] == '(') {
                array_push($arrStack, '(');
            } elseif ($input[$i] == ')' && '(' != array_pop($arrStack)) {
                return '计算表达式不合法,缺少左括号';
            }
    }

    if(!empty($arrStack)) {
        return '计算表达式不合法,缺少右括号';
    }

    return '计算表达式合法';
}

$result = isValid($input1);
var_dump($result);
$result = isValid($input2);
var_dump($result);
$result = isValid($input3);
var_dump($result);
$result = isValid($input4);
var_dump($result);

其实这个问题实际上是判断一个计算表达式中的左右括号是否合法的常用算法,算法的能力还是有待提升啊,Mark一下。

总结:
遇到问题时,先分析清楚最重要,针对问题的各种情况去分析,然后给出解决方案,这样最终才能解决该问题。切记,要先想清楚比较好。

大家如果有更好的判断方案,欢迎评论上给出好的代码实现方案

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值