​​763. 划分字母区间​​

题目描述

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

示例:

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

提示:

  • ​S​​​的长度在​​[1, 500]​​之间。
  • ​S​​​只包含小写字母​​'a'​​​ 到​​'z'​​ 。

解析


题述中同一个字母只能出现在同一个片段中,所以可以求出每个片段中字符出现的最远位置,以这个最远位置作为分界点来进行分段。


  • 步骤
  • 定义数组​​vector<int> pos​​记录每个字符出现的最远位置
  • 这里不考虑大写字母,所以数组的大小可以指定为​​26​
  • 对数组进行初始化 ,值全部初始化为​​0​
  • 分割片段
  • 每个片段区间使用​​[left,right]​​来记录长度
  • 分割点的确定
  • 如果字符出现的最远位置等于当前遍历到的索引,就将最远位置作为分割点
  • 更新本片段的右边界​​right​​​,更新下一个片段的左边界​​left​
  • 记录区间的长度并加入到结果集中

代码

class Solution
{
public:
vector<int> partitionLabels(string s)
{
// 题述中只考虑小写字母,
// 所以可以定义一个长度为26的数组记录每个字符出现的最远位置
// 这里 a的下标对应为0,z的下标对应25
int pos[26] = {0};

// 遍历字符串中的字符,记录每个字符出现的最远位置
for (int i = 0; i < s.size(); i++)
{
pos[s[i] - 'a'] = i;
}

// 结果集
vector<int> result;
// 记录区间的左边界
int left = 0;
// 记录区间的右边界
int right = 0;

// 遍历字符串
for (int i = 0; i < s.size(); i++)
{
// 找到字符出现的最远位置,作为本片段区间的右边界
right = max(right, pos[s[i] - 'a']);
if (i == right)
{

// 更新下一个分割片段区间的的左边界
left = i + 1;
// 记录每个片段的长度
result.push_back(right - left + 1);
}
}

return result;
}
};