2405. 子字符串的最优划分
题目描述
给你一个字符串 s
,请你将该字符串划分成一个或多个 子字符串 ,并满足每个子字符串中的字符都是 唯一 的。也就是说,在单个子字符串中,字母的出现次数都不超过 一次 。
满足题目要求的情况下,返回 最少 需要划分多少个子字符串。
注意,划分后,原字符串中的每个字符都应该恰好属于一个子字符串。
示例 1:
输入:s = "abacaba" 输出:4 解释: 两种可行的划分方法分别是 ("a","ba","cab","a") 和 ("ab","a","ca","ba") 。 可以证明最少需要划分 4 个子字符串。
示例 2:
输入:s = "ssssss" 输出:6 解释: 只存在一种可行的划分方法 ("s","s","s","s","s","s") 。
提示:
1 <= s.length <= 105
s
仅由小写英文字母组成
解法
方法一:贪心
根据题意,每个子字符串应该尽可能长,且包含的字符唯一,因此,我们只需要贪心地进行划分即可。
我们定义一个二进制整数 \(\textit{mask}\) 来记录当前子字符串中出现的字符,其中 \(\textit{mask}\) 的第 \(i\) 位为 \(1\) 表示第 \(i\) 个字母已经出现过,为 \(0\) 表示未出现过。另外,我们还需要一个变量 \(\textit{ans}\) 来记录划分的子字符串个数,初始时 \(\textit{ans} = 1\)。
遍历字符串 \(s\) 中的每个字符,对于每个字符 \(c\),我们将其转换为 \(0\) 到 \(25\) 之间的整数 \(x\),然后判断 \(\textit{mask}\) 的第 \(x\) 位是否为 \(1\),如果为 \(1\),说明当前字符 \(c\) 与当前子字符串中的字符有重复,此时 \(\textit{ans}\) 需要加 \(1\),并将 \(\textit{mask}\) 置为 \(0\);否则,将 \(\textit{mask}\) 的第 \(x\) 位置为 \(1\)。然后,我们将 \(\textit{mask}\) 更新为 \(\textit{mask}\) 与 \(2^x\) 的按位或结果。
最后,返回 \(\textit{ans}\) 即可。
时间复杂度 \(O(n)\),其中 \(n\) 为字符串 \(s\) 的长度。空间复杂度 \(O(1)\)。
1 2 3 4 5 6 7 8 9 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
1 2 3 4 5 6 7 8 9 10 11 12 |
|
1 2 3 4 5 6 7 8 9 10 11 12 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|