LeetCode 划分字母区间(贪心策略)

版权声明:本文为博主原创文章,博客地址:https://blog.csdn.net/qq_41855420,未经博主允许不得转载。 https://blog.csdn.net/qq_41855420/article/details/89848881
描述:

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

示例 1:
输入: S = "ababcbacadefegdehijhklij"
输出: [9,7,8]
解释:
划分结果为 "ababcbaca", "defegde", "hijhklij"。
每个字母最多出现在一个片段中。
像 "ababcbacadefegde", "hijhklij" 的划分是错误的,因为划分的片段数较少。
注意:
S的长度在[1, 500]之间。
S只包含小写字母'a'到'z'。

\color{blue}{思路分析:} 这道题我们采用贪心策略,尽可能让每一个子串长度最短。蛋式由于[left ,… minRight](left指当前字符串的起始下标,minRight是S[left]最后出现的下标)中间可能出现某个字符最后出现的下标在minRight之外,这时我们就得不断更新minRight,直到left、minRight中所有的字符都只出现在这个字符串。

class Solution {
public:
	vector<int> partitionLabels(string S) {
		int strSize = S.size();
		//第一步:统计各个字母最后一次出现的下标
		vector<int> last(26, 0), resVec;
		for (int index = 0; index < strSize; ++index) {
			last[S[index] - 'a'] = index;
		}
        //第二步:从左到右扫描字符串,采取贪心策略,一直扩大当前子串的右边界
		int left = 0, right = 0, minRight = 0;//当前子串的最小右边界
		while (left < strSize) {
			right = left + 1;//right用于扫描[left, minRight]这一段字符串
            minRight = last[S[left] - 'a'];//S[left]最后出现的下标
            //如果minRight大于right,则maxRight仍然需要更新,因为在[left, minRight]中可能有字符最后一次出现的下标在这之后
			while (right < strSize && minRight >= right) {
                minRight = max(minRight, last[S[right] - 'a']);//更新最小右边界
				++right;
			}
            resVec.push_back(right - left);//当前子串的最小长度
            left = right;
		}
		return resVec;
	}
};

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_41855420/article/details/89848881