763. Partition Labels的C++解法
阿新 • • 發佈:2018-12-10
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; } };