LeetCode 358. Rearrange String k Distance Apart
原题链接在这里:https://leetcode.com/problems/rearrange-string-k-distance-apart/description/
题目:
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:
s = "aabbcc", k = 3 Result: "abcabc" The same letters are at least distance 3 from each other.
Example 2:
s = "aaabc", k = 3 Answer: "" It is not possible to rearrange the string.
Example 3:
s = "aaadbbcc", k = 2 Answer: "abacabcd" Another possible answer is: "abcabcda" The same letters are at least distance 2 from each other.
题解:
Greedy问题. 感觉上是应该先排剩余frequency 最多的Character.
用maxHeap来维护剩余的Character, 根据剩余的count.
那么如何保持断开的距离大于k呢, 用queue来存放已经加过的Character, 只有当queue的size等于k时, 才允许把头上的Character放回到maxHeap中.
Time Complexity: O(n). n = s.length(). HashMap size could be 26. 都加入进maxHeap用时O(nlog26).
Space: O(n).
AC Java:
1 class Solution { 2 public String rearrangeString(String s, int k) { 3 if(s == null || s.length() == 0){ 4 return s; 5 } 6 7 HashMap<Character, Integer> hm = new HashMap<Character, Integer>(); 8 for(int i = 0; i<s.length(); i++){ 9 hm.put(s.charAt(i), hm.getOrDefault(s.charAt(i), 0)+1); 10 } 11 12 PriorityQueue<Map.Entry<Character, Integer>> maxHeap = new PriorityQueue<Map.Entry<Character, Integer>>( 13 (a, b) -> b.getValue() - a.getValue() 14 ); 15 maxHeap.addAll(hm.entrySet()); 16 17 LinkedList<Map.Entry<Character, Integer>> que = new LinkedList<Map.Entry<Character, Integer>>(); 18 StringBuilder sb = new StringBuilder(); 19 while(!maxHeap.isEmpty()){ 20 Map.Entry<Character, Integer> cur = maxHeap.poll(); 21 sb.append(cur.getKey()); 22 cur.setValue(cur.getValue()-1); 23 que.add(cur); 24 25 if(que.size() < k){ 26 continue; 27 } 28 29 Map.Entry<Character, Integer> head = que.poll(); 30 if(head.getValue() > 0){ 31 maxHeap.add(head); 32 } 33 } 34 return sb.length() == s.length() ? sb.toString() : ""; 35 } 36 }
时间上可以优化.
利用两个int array, count计数剩余frequency, validPo代表这个字符能出现的最早位置.
找到最大frequency的合法字符, 更新其对应的frequency 和 再次出现的位置.
Time Complexity: O(s.length()). findMaxValidCount走了遍长度为i26的count array.
Space: O(s.length()). StringBuilder size.
AC Java:
1 class Solution { 2 public String rearrangeString(String s, int k) { 3 if(s == null || s.length() == 0){ 4 return s; 5 } 6 7 int [] count = new int[26]; 8 int [] validPo = new int[26]; 9 for(int i = 0; i<s.length(); i++){ 10 count[s.charAt(i)-'a']++; 11 } 12 13 StringBuilder sb = new StringBuilder(); 14 for(int i = 0; i<s.length(); i++){ 15 int po = findMaxValidCount(count, validPo, i); 16 if(po == -1){ 17 return ""; 18 } 19 20 sb.append((char)('a'+po)); 21 count[po]--; 22 validPo[po] = i+k; 23 } 24 return sb.toString(); 25 } 26 27 private int findMaxValidCount(int [] count, int [] validPo, int ind){ 28 int po = -1; 29 int max = Integer.MIN_VALUE; 30 for(int i = 0; i<count.length; i++){ 31 if(count[i]>0 && count[i]>max && ind>=validPo[i]){ 32 max = count[i]; 33 po = i; 34 } 35 } 36 37 return po; 38 } 39 }