一、问题描述
给你一个字符串s,它包含一些括号对,每个括号中包含一个非空的键。
- 比方说,字符串“(name) is (age) years old”中,有两个括号对,分别包含键“name”和“age”。
你知道许多键对应的值,这些关系由二维字符串数组knowledge表示,其中knowledge[i]=[keyi,valuei],表示键keyi对应的值为valuei。
你需要替换所有的括号对,当你替换一个括号对,且它包含的键为keyi时,你需要: - 将keyi和括号用对应的值valuei替换。
- 如果从knowledge中无法得知某个键对应的值,你需要将keyi和括号用问好“?”替换(不需要引号)。
knowledge中每个键最多只会出现一次。s中不会有嵌套的括号。
请你返回替换所有括号对后的结果字符串。
示例1:
输入:s = “(name)is(age)yearsold”, knowledge = [[“name”,“bob”],[“age”,“two”]]
输出:“bobistwoyearsold”
解释:
键 “name” 对应的值为 “bob” ,所以将 “(name)” 替换为 “bob” 。
键 “age” 对应的值为 “two” ,所以将 “(age)” 替换为 “two” 。
示例2:
输入:s = “hi(name)”, knowledge = [[“a”,“b”]]
输出:“hi?”
解释:由于不知道键 “name” 对应的值,所以用 “?” 替换 “(name)” 。
示例3
输入:s = “(a)(a)(a)aaa”, knowledge = [[“a”,“yes”]]
输出:“yesyesyesaaa”
解释:相同的键在 s 中可能会出现多次。
键 “a” 对应的值为 “yes” ,所以将所有的 “(a)” 替换为 “yes” 。
注意,不在括号里的 “a” 不需要被替换。
二、解题思路
2.1 map+stack
这个题目最普通的思路就是找个栈存放“()”,提取出括号内的内容即key,然后去knowledge中寻找key是否存在,根据替换规则替换字符串,并返回最终结果。
具体代码如下:
/**
* @param {string} s
* @param {string[][]} knowledge
* @return {string}
*/
var evaluate = function(s, knowledge) {
let stack=[];
let key="";
let res="";
let map=new Map();
for(let item of knowledge){
map.set(item[0],item[1]);
}
for(let item of s){
if(item=="("){
stack.push(item);
key="";
}else if(item==")"){
stack.pop();
if(map.has(key)){
res+=map.get(key);
}else{
res+="?";
}
}else if(stack.length){
key+=item;
}else{
res+=item;
}
}
return res;
};
2.2、正则替换
理解题意之后我们可以直接体会到本题的核心就是字符串模板替换,对于字符串str=‘${name} is ${age} years old’,其实就是将占位符${ }换位()。
这里可以将二维数组knowledge转化为map对象,因为二维数组可能会很大,每次都去遍历查找,可能会导致超时。
核心原则:
/(([a-z]+))/g 这个正则看起来应该没有什么难度吧?(和)表示转义括号,[a-z]+ 表示匹配小写字母。
var evaluate=function(s,knowledge){
//将数组转化为Map字典,减少搜索时间
const map=new Map;
knowledge.forEach(item=>{map[item[0]]=item[1];});
s=s.replace(/\(([a-z]+)\)/g,function(p1,p2){
return map[p2]||'?';
})
return s;
};
三、知识补充
3.1 replace()用法解析
replacr函数的语法:stringobject.replace(regexp/substr,replacement)。
其中regexp/substr是必需的,规定字符串或要替换的模式的regexp对象。(请注意,如果该值是一个字符串,则将它作为要检索的直接量文本模式,而不是首先被转换为 regexp 对象。) replacement必需。一个字符串值。规定了替换文本或生成替换文本的函数。最后返回一个新的字符串,是用replacement替换了regexp的第一次匹配或所有匹配之后得到的。
ECMAScript规定,replace()方法的参数replacement可以是函数而不是字符串。在这种情况下,每个匹配都调用该函数,它返回的字符串将替换文本使用。第一个参数表示匹配到的字符,第二个参数表示匹配到的字符最小索引位置(RegExp.index),第三个参数表示被匹配的字符串(RegExp.input)。
3.2 forEach()用法解析
用于调用数组中的每个元素,