1. 程式人生 > >LeetCode 763劃分字母區間

LeetCode 763劃分字母區間

題目詳情

字串 S 由小寫字母組成。我們要把這個字串劃分為儘可能多的片段,同一個字母只會出現在其中的一個片段。返回一個表示每個字串片段的長度的列表。

示例 1:

輸入: S = "ababcbacadefegdehijhklij"
輸出: [9,7,8]
解釋:
劃分結果為 "ababcbaca", "defegde", "hijhklij"。
每個字母最多出現在一個片段中。
像 "ababcbacadefegde", "hijhklij" 的劃分是錯誤的,因為劃分的片段數較少。

注意:

  1. S的長度在[1, 500]之間。
  2. S只包含小寫字母'a''z'

題目分析

此題關鍵的想法就是找到能分割的條件, 對S的每個字元進行判斷, 看是否此字元是被分割到另一個字元中。

通過分析題目可以知道, 要求一個字元只能出現在一個字串裡, 這裡可以知道第一個條件:

  • 當此字元在前面分割的出現,就不能當做分割點

但是這個條件顯然是不夠的,當出現前面分割的字串沒出現的字元時, 是不是能直接加進去呢? 這是不行的 考慮分割此字串 aaaaabcdaefgh 當判斷b的時候, 首先在前面已經分好的字串aaaaa裡面沒有,符合條件。所以我們把b當做新的分割點。 單著顯然是錯誤的,因為在b後面的字串裡,出現了a, 當我們以b作為分割點的話必定有兩個分割的字串,不符合條件。 所以第二個限制條件:

  • 分割點後面不能出現前面一個字串中的字元

綜上條件我們可以得到結果

AC程式碼

class Solution {
public: vector<int> partitionLabels(string S) { //分割點前的字串的字元種類 (這裡不用存一個完整的字串,只需要存字串出現的種類就可以) string contain_char = ""; //前一個字串的長度 int strLen = 0; //返回的陣列 vector<int> re; for (int i = 0; i < S.size(); i++) { //當沒有字串被分割時 if
(contain_char.size() == 0) { contain_char += S[i]; strLen++; continue; } //如果當前字母在原來的字串裡 就加入進去 if (contain_char.find(S[i]) != string::npos) { strLen++; } else { //如果上一個string的包含的字元 在此字母后的string出現 //則說明此字元不是分割的地方, 把此字元加入到string //而且更新contain_char bool flag = false; for (auto singleChar : contain_char) { //後面有字元 if (S.find(singleChar, i+1) != string::npos) { flag = true; } } //如果後面有字元 就把當前字元加入到前面的字串裡 if (flag) { contain_char += S[i]; strLen++; } else { contain_char = ""; contain_char += S[i]; re.push_back(strLen); strLen = 1; } } } re.push_back(strLen); return re; } };

總結

此題利用貪心演算法是我對每一個S的字元, 在能把這個字元分離的情況下。 對每一個字元進行判斷, 這樣得到的字串的數目應該是最多的