题目
给你一个字符串s,它包含一些括号对,每个括号中包含一个非空的键。
- 比方说,字符串"(name)is(age)yearsold"中,有两个括号对,分别包含键"name"和"age"。
你知道许多键对应的值,这些关系由二维字符串数组knowledge表示,其中knowledge[i] = [keyi, valuei],表示键keyi对应的值为valuei。你需要替换所有的括号对。当你替换一个括号对,且它包含的键
为 keyi 时,你需要: - 将keyi和括号用对应的值valuei替换。
- 如果从knowledge中无法得知某个键对应的值,你需要将keyi和括号用问号"?"替换(不需要引号)。knowledge中每个键最多只会出现一次。s中不会有嵌套的括号。
请你返回替换所有括号对后的结果字符串。
示例
- 输入:s = “(name)is(age)yearsold”, knowledge = [[“name”,“bob”],[“age”,“two”]]
- 输出:“bobistwoyearsold”
- 解释:键 “name” 对应的值为 “bob” ,所以将 “(name)” 替换为 “bob” 。键 “age” 对应的值为 “two” ,所以将 “(age)” 替换为 “two” 。
题解
感觉leetcode的题解稍显复杂,简单的问题描述的比较不容易理解。这个题目其实很简单,就是给定一个字符串,找出()里的单词,其实knowledge可以理解为一个替换字典[{key,value}],如果()里的单词在这个字典里,用字典的value替换这个单词,如不在字典里则用"?"替换。这里的核心是把()与其他的字符串区分开,这里采用双指针来实现。没有特别复杂的算法,这是以示例简单介绍一个实现的过程。这里需要一个start来标记(一个end来标记)。这样通过start与end可以确定()内的字符,以及未在()的字符串。下面通过上面示例给出双指针的处理过程。
初始start指向s的第一个字符,end指向-1,这是处理以(开始的字符串。
开始对整个字符串s进行遍历,当碰到(后,这里end+1到start的之间的字符串在()之外,直接把这个字符串加入到结果串。s中的第一个字符即为(,end为-1,end+1到0为空则括号外的字符串为空因此ans也为空。继续遍历到碰到)时,end指向)字符。这里start+到end之间的字符串为name。通过查找knowledge中的字典发现name需要替换为bob。结果如下:
继续进行遍历直到碰到下一个(字符串,start指向该字符串。同时标记end+1到start为()外的字符串,不需要处理直接加入到ans中。过程如下图。
最后到终止的时候需要处理一下把end+1到末尾的字符串直接加入到ans即可。
过程整理
到这里整个流程比较清晰了:
- 1 把kowledge变成哈希表加速查找
- 2 初始start=1,end=-1
- 3 当碰到(时start变为当前索引,然后把end+1到start的字符串加入ans
- 4 当遍历到),end更新为当前索引,判断start+1到end的字符串是否在knowledge中,如在value加到ans,不在"?"加入到ans。
- 5 遍历结束把end+1到末尾的直接加入到ans。
代码
下面可以写代码了:
class Solution:
def evaluate(self, s: str, knowledge: List[List[str]]) -> str:
#knowledge要转换成dic
knowledge_dic=dict(knowledge)
n=len(s)
start=0
end=-1
ans=""
for i in range(len(s)):
if s[i]=="(":
start=i
ans+=s[end+1:start]
if s[i]==")":
end=i
word=s[start+1:end]
print(word)
if word in knowledge_dic:
ans+=knowledge_dic[word]
else:
ans+="?"
ans+=s[end+1:]
return ans
计算复杂度
- 时间复杂性:整个过程是一次遍历s,s的长度为n,则复杂度为 O ( n ) O(n) O(n),构建hash表示需要处理knowledge,kowledge的长度为k的话,复杂度为 O ( n ) O(n) O(n)。因此整体的时间复杂度为 O ( n + k ) O(n+k) O(n+k)
- 空间复杂性:整个过程需要存储hash表与ans,因此复杂度为 O ( n + k ) O(n+k) O(n+k)