leetcode每日一题---List转(MAP)hash表

1807. 替换字符串中的括号内容

给你一个字符串 s ,它包含一些括号对,每个括号中包含一个 非空 的键。

  • 比方说,字符串 "(name)is(age)yearsold" 中,有 两个 括号对,分别包含键 "name" 和 "age" 。

你知道许多键对应的值,这些关系由二维字符串数组 knowledge 表示,其中 knowledge[i] = [keyi, valuei] ,表示键 keyi 对应的值为 valuei 。

你需要替换 所有 的括号对。当你替换一个括号对,且它包含的键为 keyi 时,你需要:

  • 将 keyi 和括号用对应的值 valuei 替换。
  • 如果从 knowledge 中无法得知某个键对应的值,你需要将 keyi 和括号用问号 "?" 替换(不需要引号)。

PS:knowledge 中每个键最多只会出现一次。s 中不会有嵌套的括号。
请你返回替换所有括号对后的结果字符串

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/evaluate-the-bracket-pairs-of-a-string
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

本题最初思路很简单,因为无论时java还是c++都自带在String中定位字符的函数,所以当时的想法是向String中依次定位'('和')',并将其前后的内容拼接即可。
所以第一次完成的代码如下

class Solution {
    public String evaluate(String s, List<List<String>> knowledge) {
        int start=0;
        int end=0;
        while(start!=-1)
        {
            start=s.indexOf('(',start);
            end=s.indexOf(')',start);
            if(start==-1) break;
            String mid=s.substring(start+1,end);
            boolean flag=false;
            for(int i=0;i<knowledge.size();i++)
            {
                if(mid.equals(knowledge.get(i).get(0)))
                {
                    s=s.substring(0,start)+knowledge.get(i).get(1)+s.substring(end+1);
                    flag=true;
                    break;
                }
            }
            if(!flag)
            {
                 s=s.substring(0,start)+"?"+s.substring(end+1);
            }
        }
        return s;
    }
}

但是结果是在执行测试用例时可以正常通过但是提交时出现超时,查看错误信息后,发现最后的测试用例中字符串和List表都长的吓人
image

查看题解提示后,了解到可以使用map来构造hash表或者说字典,来缩短时间。
于是有了第二版代码

class Solution {
    public String evaluate(String s, List<List<String>> knowledge) {
        int start=0;
        int end=0;
        Map<String,String> hashkonw =new HashMap();
        for(List<String> kd : knowledge)//
        {
            hashkonw.put(kd.get(0),kd.get(1));
        }//构造字典
        while(start!=-1)
        {
            start=s.indexOf('(',start);
            end=s.indexOf(')',start);
            if(start==-1) break;
            String mid=s.substring(start+1,end);
            if(hashkonw.get(mid)!=null)
            {
                s=s.substring(0,start)+hashkonw.get(mid)+s.substring(end+1);
            }
            else
            {
                 s=s.substring(0,start)+"?"+s.substring(end+1);
            }
        }
        return s;
    }
}

结果时通过了但是用时900多ms,空间消耗也极大,效率极为低下,所以查看了题解的思路,发现所有的题解都无一例外使用了StringBuilder来记录截取到的数据和结果,对于需要追加的数据直接利用append来添加。

查询后发现:String 类型的每次重新赋值都相当于重新开辟一个新的空间来进行数据的存储,所以频繁的对String 重新赋值会极大的影响效率而和使用StringBuilder则不会有这样的问题

最终版代码如下:

class Solution {
    public String evaluate(String s, List<List<String>> knowledge) {
        int start=0;
        int end=0;
        Map<String,String> hashkonw =new HashMap();
        for(List<String> kd : knowledge)
        {
            hashkonw.put(kd.get(0),kd.get(1));
        }//大量数据用hash表避免大量便利耗费时间
        StringBuilder res=new StringBuilder();//利用stringbuilder.append比重新对s赋值更快
        for(int i=0;i<s.length();i++)
        {
            if(s.charAt(i)=='(')
            {
                int next=s.indexOf(')',i+1);
                String mid=hashkonw.get(s.substring(i+1,next));
                if(mid!=null)
                res.append(mid);
                else
                res.append("?");
                i=next;
            }
            else res.append(s.charAt(i));
        }
        return res.toString();
    }
}

效率提升到了30ms,成功!!!!

posted @ 2023-01-13 16:27  比奇堡的黄色小海绵  阅读(47)  评论(0)    收藏  举报