2405. 子字符串的最优划分【双指针】【滑动窗口】

题目

给你一个字符串 s ,请你将该字符串划分成一个或多个 子字符串 ,并满足每个子字符串中的字符都是 唯一 的。也就是说,在单个子字符串中,字母的出现次数都不超过 一次 。

满足题目要求的情况下,返回 最少 需要划分多少个子字符串。

注意,划分后,原字符串中的每个字符都应该恰好属于一个子字符串。

难度:中等

提示:

  • 1 <= s.length <= 105
  • s 仅由小写英文字母组成

题解

要求子字符串内的字符唯一,那么可以通过双指针确定范围,左指针确定起始位置,右指针确定尾部,遍历的时候维护一个表来确定是否字符重复,可以用set,但是题目只有小写字母,也可以自己通过一维数组自己维护一张表

Set版本-32 ms

class Solution {
    public int partitionString(String s) {
        Set<Character> set = new HashSet<>();
        char[] chars = s.toCharArray();
        List<String> list = new LinkedList<>();
        int l = 0, r = 0;
        while (r < chars.length) {
            if (!set.contains(chars[r])) {
                set.add(chars[r]);
            } else {
                list.add(s.substring(l, r));
                l = r;
                set.clear();
                r--;
            }
            r++;
        }
        list.add(s.substring(l,r));
        return list.size();
    }
}

复杂度分析

  • 时间复杂度:O(N)
  • 空间复杂度:O(N)

数组表-8 ms

后面发现,需要统计次数,不需要具体的子字符串,所以直接统计就行

class Solution {
    public int partitionString(String s) {
        char[] chars = s.toCharArray();
        int[] cnts = new int[26];
        Arrays.fill(cnts, -1);
        int res = 0;
        int r = 0;
        while (r < chars.length) {
            if (cnts[chars[r] - 'a'] == -1) {
                cnts[chars[r] - 'a']++;
            } else {
                res++;
                Arrays.fill(cnts, -1);
                r--;
            }
            r++;
        }
        return ++res;
    }
}

复杂度分析

  • 时间复杂度:O(N)
  • 空间复杂度:O(C)
posted @ 2022-09-17 13:37  tothk  阅读(40)  评论(0编辑  收藏  举报