一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情。
今天要学习的内容是如何判断字符串是否括号匹配。
1、题目分析
什么是括号匹配呢?让我们先了解一下括号,我们用到的有大括号{},小括号(),中括号[],这样的组合就是正确匹配的,但是如果不是上方列举的三种形式,那么就是不匹配的。
举例:
匹配:"{123[222(456)]}"
不匹配: "{([123)555]}"
2、解题思路
这道题目主要考察的是对栈的理解和使用,我们可以通过使用数组来模拟栈来进行解题。
- 延展:栈和数组的区别是什么呢?
- 栈是逻辑结构。它是一种理论模型,它是一种先进后出的模型,它不用考虑如何实现,不受语言的限制;
- 数组是一种物理结构。它受编程语言的限制,有真实的功能,具体的操作方法。
数组可以实现栈,还有其他方式也可以实现栈,但栈无法实现数组。
我们可以通过使用数组模拟栈,通过将左括号压栈,右括号判断栈顶是否匹配,如果不匹配则返回false,如果匹配则出栈,继续向后查找。字符串查找完毕后,再判断栈的长度是否为0;
解题
function matchBrackets(str: string): boolean{
const length = str.length;
if(length === 0) return true; //如果字符串长度为0,那么其中不会存在括号,判断其符合括号匹配
const stack = [];
const leftBtackets = "{[(";
const rightBtackets = ")]}";
for(let i=0; i<length; i++){
if(leftBtackets.includes(str[i])){//如果是左括号,进行入栈操作
//if(str[i] === '{' || str[i] === '[' || str[i] === '(' ){
stack.push(str[i])
}else if(rightBtackets.includes(str[i])){//如果是右括号,判断其是否和栈顶的元素相匹配,
//}else if(str[i] === '}' || str[i] === ']' || str[i] === ')'){
const top = stack[stack.length - 1];//这里四栈顶元素
if(ifMatch(top,str[i])){//如果匹配,那么则进行出栈操作,并继续向下进行。这里的判断可以再写一个方法
stack.pop()
}else{//如果不匹配,那么这个字符串就是括号不匹配的,返回false
return false
}
}
}
if(stack.length === 0) return true;
return false
}
function ifMatch(left:string, right:string): boolean{
if(left === "{" && right === "}") return true;
if(left === "[" && right === "]") return true;
if(left === "(" && right === ")") return true;
return false
}
功能测试
const str1 = "{44}[(12)44]"
const bol1 = matchBrackets(str1);
console.log(bol1)//true 符合预期
const str2 = "{44[(12})44]"
const bol2 = matchBrackets(str2);
console.log(bol2)//false 符合预期
const str3 = "{44[(12)}44]"
const bol3 = matchBrackets(str3);
console.log(bol3)//false 符合预期
复杂度分析
空间复杂度是O(n)
- 这里通过改变输入变量str的增大,函数体内创建的变量stack的长度会变大(可能性比较大,不要考虑增长字符串却不添加括号),其占用的空间不是一成不变的,所以空间复杂度是O(n)
时间复杂度是O(n) - 这里使用了includes,理论上includes的时间复杂度也是O(n),其外边右套了一层循环,为什么不是O(n^2)而是O(n)呢?这主要是因为虽然理论上includes的时间复杂度也是O(n),但是其遍历的内容是固定的,而且非常短leftBtackets = "{[(";rightBtackets = ")]}";所以可以将其在此处的时间复杂度默认为O(1);综合考虑其时间复杂度是O(n).如果实在不能理解,可以看看函数中注视掉的代码来替换inckudes,只是代码不如使用includes美观优雅而已。
3、总结
这道题重点在考察栈的理解与使用,这次没有做性能分析,主要是因为只提供了一种思路,而且其复杂度比较合适。另外虽然有些JS的内置方法时间复杂度可能会比较高,但也要考虑实际的使用情景。