leetCode763--划分字母区间

356 阅读2分钟

问题描述

leetcode.763.划分字母区间

字符串 S 由小写字母组成。我们要把这个字符串划分为尽可能多的片段,同一个字母只会出现在 其中的一个片段。返回一个表示每个字符串片段的长度的列表

示例1

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

问题分析

思路

我们从左开始遍历字符串,然后找到每一个可分割的子串,比如第一个字符是‘a’,那么被分割的字符串必须包含所有‘a’,这是我们可以找到一个字符子串‘ababcbaca’,但是该区间里还有别的字符,比如字符串‘abab’,‘aba’这个子串中有一个‘b’,所以我们需要扩大子串,将所有的‘b’包含进来,就得到了一个新的子串‘abab’,这样一直遍历下去,找到左右子串。

算法

定义数组index[i]表示字符i所出现的最后位置,然后定义start和end来表示当前区间的首尾,若遇到的字符的index[i]大于end,则让end = index[i]来扩大区间,若i == end意味着遍历到了当前区间的末尾,则记录其长度,然后继续遍历下一个区间,令start == i + 1;

代码

int* partitionLabels(char * S, int* returnSize){
    *returnSize = 0;
    int index[26] = {0};
    int start = 0, last = 0, end = 0;
    int* res = (int*)malloc(sizeof(int)*500);
    //index数组用于存放每个字符出现的最后的位置
    for(int i = 0; i < strlen(S); i++)
    {
        index[S[i] - 'a'] = i;
    }
    for(int i = 0; i < strlen(S); i++)
    {
        //若新字符的最后位置比last大,就更新
        last = last > index[S[i] - 'a'] ? last : index[S[i] - 'a']; 
        //相等说明该子串满足条件,可分割
        if(i == last){
            res[end++] = last - start + 1;
            last = i + 1;
            start = i + 1;
        }
    }
    *returnSize = end;
    return res;
}

时间复杂度和空间复杂度

  • 时间复杂度O(n): index数组复制需要时间O(n),然后寻找子串又需要O(n),所以总的时间复杂度为O(n)
  • 空间复杂度O(1): 程序消耗固定的空间,所以空间复杂度为O(1)