69 划分字母区间

划分字母区间

    • 题解1 贪心1(方法略笨,性能很差)
    • 题解2 贪心2(参考标答)

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

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

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

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

示例 2:
输入:s = "eccbbbbdec"
输出:[10]

提示:

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

题解1 贪心1(方法略笨,性能很差)

每次都在找当前字符所在的最大下标k,可以保证该片段的最小长度n>k-begin

class Solution {
public:
    vector<int> partitionLabels(string s) {
        int sl = s.size();
        vector<int> ret;

        int k = s.rfind(s[0]);
        while(k >= 0 && k < sl){
            set<char> tmp;
            int end = sl-1;
            for(int i = 0; i <= k; i++){
               tmp.insert(s[i]);
            }
            // 方向:从后往前
            // 原则:尽量多划,不在上一个段的也先选择划开
            while(end > k && !tmp.count(s[end])){
                end --;
                // 如果发现有重复字符 重新找k和end
                // 参考题解2 有更好的找最远位置的方法(last数组)
                if(end > k && tmp.count(s[end])){
                    for(int i = k+1; i <= end; i++)
                        tmp.insert(s[i]);
                    k = end;
                    end = sl-1;
                }
            }
            ret.push_back(end);
            if(end < sl-1)
                k = s.rfind(s[end+1]);
            else break;
        }
		// ret开始存的是下标,但题目要求返回长度(审题)
        for(int i = ret.size()-1; i > 0; i--)
            ret[i] = ret[i] - ret[i-1];
        ret[0] ++;

        return ret;
    }
};

69 划分字母区间_第1张图片

题解2 贪心2(参考标答)

class Solution {
public:
    vector<int> partitionLabels(string s) {
        int last[26];
        int length = s.size();
        for (int i = 0; i < length; i++) {
            // 下标从小到大:从左往右:每个字符对应的位置都是最远位置
            // 反之,最近位置
            last[s[i] - 'a'] = i;
        }
        vector<int> partition;
        int start = 0, end = 0;
        for (int i = 0; i < length; i++) {
            // 在子串中去寻找最大的end值
            end = max(end, last[s[i] - 'a']);
            // 重点!! 找到最大的end值后,i没有遍历到下一个子串前不会再有更大的end值
            if (i == end) {
                partition.push_back(end - start + 1);
                start = end + 1;
            }
        }
        return partition;
    }
};

69 划分字母区间_第2张图片

你可能感兴趣的:(贪心,HOT100,子串,算法,数据结构,leetcode)