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 }

类似Task SchedulerReorganize String.

posted @ 2017-10-27 14:42  Dylan_Java_NYC  阅读(958)  评论(0编辑  收藏  举报