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 };