算法初探LeetCode-划分字母区间

106 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 3 天,点击查看活动详情

LeetCode763:划分字母区间

给你一个字符串 s 。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。

注意,划分结果需要满足:将所有划分结果按顺序连接,得到的字符串仍然是 s 。

返回一个表示每个字符串片段的长度的列表。

示例 1:

输入: s = "ababcbacadefegdehijhklij"
输出: [9,7,8]
解释:
划分结果为 "ababcbaca""defegde""hijhklij" 。
每个字母最多出现在一个片段中。
像 "ababcbacadefegde", "hijhklij" 这样的划分是错误的,因为划分的片段数较少。 

示例 2:

输入: s = "eccbbbbdec"
输出: [10]

提示:

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

思路分析

根据题目分析,要求尽可能多划分片段,同一字母只能出现在一个片段中,如何知道片段中的字母都不会出现在其他片段呢?

  • 1.可以先统计字符串 s 中的各个字母出现次数存放在数组 letter 中
  • 2.遍历字符串 s ,进行截取 s 片段并统计片段中各个字母出现次数存放在一个数组 fragment 中
  • 3.用 fragment 与字典数组 letter 进行比较,当 fragment 数组中不为0的元素与 letter 数组元素相等时即划分成功

算法代码

public List < Integer > partitionLabels(String s) {
        List < Integer > list = new ArrayList < > ();

        int[] letter = letterCount(s); //字典数组
        int[] fragment = new int[26]; //统计截取片段的字母种数及对应的数量
        int start = 0;
        int end = 1;
        while (end <= s.length()) {
            fragment = letterCount(s.substring(start, end));
            if (isFull(letter, fragment)) {
                list.add(end - start);
                start = end;
            }
            end++;
        }
        return list;
    }
    //统计输入的字符串a中各个字母出现次数
public int[] letterCount(String a) {
        int[] letter = new int[26];
        for (int i = 0; i < a.length(); ++i) {
            int temp = a.charAt(i) - 'a';
            letter[temp] ++;
        }
        return letter;
    }
    //检验testArray数组是否已将含有的字母全部截取
public boolean isFull(int[] hostArray, int[] testArray) {
    for (int i = 0; i < hostArray.length; ++i) {
        if (testArray[i] > 0) {
            if (hostArray[i] != testArray[i]) {
                return false;
            }
        }
    }
    return true;
}

结果详情

Snipaste_2023-02-06_23-35-45.png

算法复杂度

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

掘金(JUEJIN)一起进步,一起成长!