LC每日一题|20240529 - 2981. 找出出现至少三次的最长特殊子字符串 I

137 阅读2分钟

LC每日一题|20240529 - 2981. 找出出现至少三次的最长特殊子字符串 I

给你一个仅由小写英文字母组成的字符串 s

如果一个字符串仅由单一字符组成,那么它被称为 特殊 字符串。例如,字符串 "abc" 不是特殊字符串,而字符串 "ddd""zz""f" 是特殊字符串。

返回在 s 中出现 至少三次最长特殊子字符串 的长度,如果不存在出现至少三次的特殊子字符串,则返回 -1

子字符串 是字符串中的一个连续 非空 字符序列。

提示:

  • 3 <= s.length <= 50
  • s 仅由小写英文字母组成。

题目等级:Medium

解题思路

分类讨论~

首先通过滑窗扫出所有尽可能长的特殊串,并记下由每个字母组成的特殊串的长度,然后将其排序。

对于某种字符组成的特殊串,有如下几种可能。

  • 只扫出来一个特殊串a,此时满足条件的特殊串长度应为 a.length - 2
  • 扫出两个特殊串a, b且长度相同,此时满足条件的最长子串应为a.length - 1
  • 扫除两个以上特殊串,其中最长的a, b长度相同,第三长的特殊串为c,此时满足条件的最长子串应为max(a.length - 1, c。length)
  • 扫出多个特殊串,且最长的两个串a, b满足a.length > b.length,此时满足条件的最长子串应为max(a.length - 2, b.length)
  • 如果最大子串长度小于等于0,按题意需要维护其为-1

AC代码

class Solution {
    fun maximumLength(s: String): Int {
        val map = HashMap<Char, ArrayList<Int>>()
        var start = 0
        for (i in s.indices) {
            if (s[i] != s[start]) {
                map[s[start]] = (map[s[start]] ?: arrayListOf()).apply { add(i - start) }
                start = i
            }
        }
        map[s[start]] = (map[s[start]] ?: arrayListOf()).apply { add(s.length - start) }
        var max = -1
        for (m in map) {
            val len = m.value.sorted()
            val a = if (len.size == 1) {
                if (len[0] > 2) len[0] - 2 else -1
            } else if (len.size == 2 || len[len.size - 1] != len[len.size - 2]) {
                if (len[len.size - 1] < 2) -1 else Math.max(len[len.size - 1] - 2, Math.min(len[len.size - 1] - 1, len[len.size - 2]))
            } else {
                Math.max(len[len.size - 3], len[len.size - 1] - 1)
            }
            max = Math.max(max, a)
        }
        return max
    }
}