Leetcode 358. Rearrange String k Distance Apart
Problem:
Given a non-empty string s and an integer k, rearrange the string such that the same characters are at least distance k from each other.
All input strings are given in lowercase letters. If it is not possible to rearrange the string, return an empty string ""
.
Example 1:
Input: s = "aabbcc", k = 3
Output: "abcabc"
Explanation: The same letters are at least distance 3 from each other.
Example 2:
Input: s = "aaabc", k = 3
Output: ""
Explanation: It is not possible to rearrange the string.
Example 3:
Input: s = "aaadbbcc", k = 2
Output: "abacabcd"
Explanation: The same letters are at least distance 2 from each other.
Solution:
百度筆試原題,當時沒做出來,現在來看這道題,依然做不出來。。。這道題用了哈希表,堆和貪心算法,感覺難度非常高,現在來看看這道題是如何解答的。首先用一個哈希表記錄每個字符出現的次數,然後將哈系表中的鍵值對推入優先級隊列中,現在的關鍵點在於如何使相同字符直接的距離為k。可以想象,出現次數多的字符應該優先考慮放置,所以這個優先級隊列是以字符出現次數作為比較函數的,隊列頂是出現次數最多的字符。所以我們每次從隊列中取出k個鍵值對,對其字符進行組合,然後將其次數減一,如果不為0就重新加入優先級隊列,由於隊列中每個鍵值對必然不存在重復字符,所以這樣做必然不會違背題意。接下來講講細節,如果可用字符串長度小於k,那麽就全部添加字符串就行了,如果說優先級隊列提前為空,說明剩下的字符不能夠繼續組合字符串,所以返回空。以第二個例子為例,第一次循環後res為“abc”,優先級隊列中還有(2,‘a‘),此時還需要放置兩個元素,但放下一個a之後優先級隊列中已經沒有元素可以放置了,說明無法得到目標字符串,所以返回空。
Code:
1 class Solution { 2 public: 3 string rearrangeString(string str, int k) { 4 if (k == 0) return str; 5 string res; 6 int len = (int)str.size(); 7 unordered_map<char, int> m; 8 priority_queue<pair<int, char>> q; 9 for (auto a : str) ++m[a]; 10 for (auto it = m.begin(); it != m.end(); ++it) { 11 q.push({it->second, it->first}); 12 } 13 while (!q.empty()) { 14 vector<pair<int, int>> v; 15 int cnt = min(k, len); 16 for (int i = 0; i < cnt; ++i) { 17 if (q.empty()) return ""; 18 auto t = q.top(); q.pop(); 19 res.push_back(t.second); 20 if (--t.first > 0) v.push_back(t); 21 --len; 22 } 23 for (auto a : v) q.push(a); 24 } 25 return res; 26 } 27 };
Leetcode 358. Rearrange String k Distance Apart