763. Partition Labels的C++解法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/musechipin/article/details/82737162

1.从第一个字母开始,找到它最后一次出现的位置,那么这一段就是当前最短的一节(因为一节需要把同一个字母全都包含进去)。但是在这一节中如果有别的字母在之后又出现了,这一节的长度需要延长到那个字母最后一次出现的位置。

2.同一个字母第一次遇到的时候其首尾之间的距离将是最大的,所以一个字母只要找一次记下来即可。

算法主要分为两个循环,第一个循环找到每个字母的首位最大距离(记录头和尾)。第二个循环顺序计算,如果某个字母的头位置超出了上一节的结尾,说明上一节结束了,开始新的一节。两个循环好像也可以合并成一个循环,我没有做,速度还是很快,4msbeat99%。

class Solution {
public:
	vector<int> partitionLabels(string S) {
		vector<int> res;
		int n = S.length();
		vector<pair<int, int>> index(26);
		vector<bool> record(26,false);
		for (int i = 0; i < n;i++)
		{
			if (record[S[i] - 'a'] == false)
			{
				int j = n - 1;
				while (S[j] != S[i]) j--;
				index[S[i] - 'a'] = make_pair(i, j);
                record[S[i] - 'a'] = true;
			}
		}
		int head = index[S[0] - 'a'].first;
		int tail = index[S[0] - 'a'].second;
		for (int i = 0; i < n; i++)
		{
			if (index[S[i] - 'a'].first > tail)
			{
				res.push_back(tail - head + 1);
				head = index[S[i] - 'a'].first;
				tail = index[S[i] - 'a'].second;
			}
			else if (index[S[i] - 'a'].second > tail) tail = index[S[i] - 'a'].second;
		}
        res.push_back(tail - head + 1);
		return res;
	}
};

emmmm看了一下别人的做法,发现其实不用记录首位置:

class Solution {
public:
    vector<int> partitionLabels(string S) {
        vector<int> last(26, 0);
        int length = (int)S.length();
        for (int i = 0; i < length; i++) {
            last[S.at(i) - 'a'] = i;
        }

        int start = 0, end = 0;
        vector<int> partition;
        for (int i = 0; i < length; i++) {
            end = max(last[S.at(i) - 'a'], end);
            if (end == i) {
                partition.push_back(end - start + 1);
                start = i + 1;
            }
        }

        return partition;
    }
};

猜你喜欢

转载自blog.csdn.net/musechipin/article/details/82737162