每日一题:1624. 两个相同字符之间的最长子字符串

130 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

题目链接:1624. 两个相同字符之间的最长子字符串

题目描述【easy】

image.png

解题思路

1.初见

本题的题意比较清晰明了,给定字符串,找出相同字符之间的最长子字符串的长度,思路比较清晰:遍历字符串,首次遍历到的字符X记录其位置startPos,继续遍历遇到X字符,计算字符X间子字符串长度,字符X可能有多个,保留最大值即可,多个不同字符间最长子字符串中最大值即为结果

代码-1.初见

    public int maxLengthBetweenEqualCharacters(String s) {
        int len = s.length();
        if (len <= 1) {
            return 0;
        }
        
        int maxLen = -1;
        
        // 记录字符首次出现的位置
        Map<Character, Integer> frequencyMap = new HashMap<>();
        for (int index = 0; index < len; ++index) {
            char ch = s.charAt(index);
            if (frequencyMap.containsKey(ch)) {
                // 更新满足题目要求的字符间最长子字符串长度
                int curLen = index - frequencyMap.get(ch) - 1;
                maxLen = curLen > maxLen ? curLen : maxLen;
            } else  {
                frequencyMap.put(ch, index);
            }
        }
        
        return maxLen;
    }
  • 时间复杂度:O(N)
  • 空间复杂度:O(N)~O(1)

2.探索

上述「1.初见」思路比较明显,实现中采用HashMap进行存储,做到O(1)时间复杂度确定字符X首次出现的位置startPos,题中给出的提示:输入字符串中只包含小写字母,可以进一步简化代码剔除HashMap,借用数组实现HashMap的快速查找能力。

代码-2.探索【伪代码】

// 数组记录字符首次出现位置 X∈[a~z]
int[] posArr = new int[26]; // init with -1
for ch in str
    if posArr[ch - 'a'] != -1
        posArr[ch - 'a'] = pos(ch);
    else
        do update maxLen
  • 时间复杂度:O(N)
  • 空间复杂度:O(26)≈O(1)

3.归途

本地题意清晰,无需多言,这里聊一下LeetCode或者说工程上常用的一种降低时间复杂度的方式,空间换时间,就本题来说,直接使用暴力求解:两层for循环进行遍历计算两个相同字符间最长子字符串,暴力求解的时间复杂度为O(N^2)空间换时间,使用长度26的数组或HashMap,可以将算法的耗时下降2个量级,整体来看收益巨大。

空间换时间

  • 原理:最早了解到的空间换时间的原理是局部性原理,简单理解就是:90%(maybe)的请求量集中在10%的数据上,通过引入缓存Cache的方式,「见封面图」,降低整体的访问耗时--即时间复杂度;
  • 应用:工程上实际业务场景,Redis、MemCache、CDN、JIT...之类都是应用局部性原理局部性原理更多了解
  • 此处应用:由于进行遍历时,程序是无状态的,通过记录遍历过程中的一些状态,剪枝遍历的次数,大大提升了程序的性能,也是局部性原理的一种应用。

4.拓展

image.png 本题题意清晰,进一步分析,想到连连看小游戏,本题本质上是寻找任意两个相同字符,其间隔的长度最大;进一步拓展,可以考虑如下的题目:

小羊最近新下载了一个游戏叫“LeetCode连连看”,游戏玩法如下,给定连连看字符串str="abbadaccda",小羊需要对字符串进行连线,进行连线时两个相同字符中的子字符串长度为消耗的能量数,连线之后的字符从字符串中剔除,直到连线完所有可以连接的字符,游戏结束,消耗能量数越少获得奖励越多,请jy们帮小羊获得最大奖励吧!

case1:

str = "abbadaccda"

最优连线方式为:bb、aa、cc、dd、aa,消耗能量数为:1(连线dd时子字符串长度为1)

道阻且长,诸位共勉!