K距离间隔重排字符串。给你一个非空的字符串 s 和一个整数 k,你要将这个字符串中的字母进行重新排列,使得重排后的字符串中相同字母的位置间隔距离至少为 k。所有输入的字符串都由小写字母组成,如果找不到距离至少为 k 的重排结果,请返回一个空字符串 ""。例子,
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.
思路类似767题,也是会用到hashmap和pq,pq存的是一个maxheap,hashmap的value大的在heap顶端。遍历input,用hashmap统计每个字符串的出现次数,将出现次数大于0的字符串放入heap,出现次数相同的则会按照字母顺序排列。之后开始从heap中弹出元素(同时需要用一个list记录弹出的元素,因为你需要这个list再把弹出但是mapvalue不为0的元素再放回maxheap),弹出的元素需要加到stringbuilder。因为要保持相同字母距离为K的关系,所以在弹出的过程中如果heap空了,需要判断此时i是否到达K了或者已经拼接好的部分和原字符串是否等长。这样可以规避掉比如第二个例子这样的corner case。
时间O(nlogn)
空间O(n)
Java实现
1 class Solution { 2 public String reorganizeString(String S) { 3 // Create map of each char to its count 4 Map<Character, Integer> map = new HashMap<>(); 5 for (char c : S.toCharArray()) { 6 int count = map.getOrDefault(c, 0) + 1; 7 // Impossible to form a solution 8 if (count > (S.length() + 1) / 2) { 9 return ""; 10 } 11 map.put(c, count); 12 } 13 // Greedy: fetch char of max count as next char in the result. 14 // Use PriorityQueue to store pairs of (char, count) and sort by count DESC. 15 PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> b[1] - a[1]); 16 for (char c : map.keySet()) { 17 pq.add(new int[] { c, map.get(c) }); 18 } 19 // Build the result. 20 StringBuilder sb = new StringBuilder(); 21 while (!pq.isEmpty()) { 22 int[] first = pq.poll(); 23 if (sb.length() == 0 || first[0] != sb.charAt(sb.length() - 1)) { 24 sb.append((char) first[0]); 25 if (--first[1] > 0) { 26 pq.add(first); 27 } 28 } else { 29 int[] second = pq.poll(); 30 sb.append((char) second[0]); 31 if (--second[1] > 0) { 32 pq.add(second); 33 } 34 pq.add(first); 35 } 36 } 37 return sb.toString(); 38 } 39 }