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一下。
总结:
遇到问题时,先分析清楚最重要,针对问题的各种情况去分析,然后给出解决方案,这样最终才能解决该问题。切记,要先想清楚比较好。
大家如果有更好的判断方案,欢迎评论上给出好的代码实现方案