一个字符串可能s可能包含{} () [] 三种括号。
如(a{b}c)匹配,而{a(b或{a(b}c)就不匹配
栈
- 先进后出
- API:push pop length
- 相关的:队列,堆
const stack=[]
stack.push(100) //入栈
stack.push(200)
stack.push(300)
const num=stack.pop() //出栈
栈和数组
数组可以实现栈,但栈不能实现数组。
逻辑结构和物理结构比较:
- 栈,逻辑结构。理论模型,不管如何实现,不受任何语言限制
- 数组,物理结构。真实的功能实现,受限于编程语言
思路:
- 遇到左括号{([就压栈
- 遇到右括号})]就判断栈顶,匹配则出栈
- 最后判断length是否为0
// 判断一个字符串是否括号匹配
/*
const stack=[]
stack.push(100) //入栈
stack.push(200)
stack.push(300)
const num=stack.pop() //出栈
*/
// isMath函数判断传入的两个值是否对应,如果对应返回true,否则返回false
function isMath(left:string,right:string):boolean{
if(left === '{' && right === '}') return true
if(left === '[' && right === ']') return true
if(left === '(' && right === ')') return true
return false
}
function matchBracket(str:string):boolean{
// 如果sr的长度为0,直接返回false
const length=str.length;
if(length===0)return true;
// 定义一个空数组,接收{[(
const stack=[];
// 定义两边将匹配的字符保存在里面
const leftSymbols='{[(';
const rightSymbol='}])';
// 对传入的字符串进行遍历
for(let i=0;i<length;i++){
// 定义一个变量接收遍历的每个元素
const s=str[i];
// 如果leftSymbols包含遍历的元素,则将该元素压入到stack数组中
if(leftSymbols.includes(s)){
stack.push(s);
// 如果rightSymbol中含有遍历到的元素,则将该元素对应stack中的元素就要出栈
}else if(rightSymbol.includes(s)){
const top=stack[stack.length-1];
// 如果左右两边的值一样且不返回false,在stack中弹出元素最后一个元素
if(isMath(top,s)){
stack.pop();
// 如果返回false,则返回false,说明字符不匹配
}else{
return false;
}
}
}
// 如果stack为0说明字符匹配,反之不匹配
return stack.length === 0
}
// 测试
const str='{a(b[c)]d)e}f'
console.info(123123,matchBracket(str))
时间复杂度和空间复杂度都是O(n)。
for循环复杂度为O(n),includes实际上也是O(n),类似于数组的查找需要遍历看每一项是否匹配。但是因为leftSymbol和rightSymbol是固定的,和str的长度没有关系,是一个固定的量,而且非常短,所以不去计算复杂度。stack不如str长,但在数量级上是一样的所以空间复杂度为O(n)。