Given a non-empty string str 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:
str = "aabbcc", k = 3

Result: "abcabc"

The same letters are at least distance 3 from each other.
Example 2:
str = "aaabc", k = 3 

Answer: ""

It is not possible to rearrange the string.
Example 3:
str = "aaadbbcc", k = 2

Answer: "abacabcd"

Another possible answer is: "abcabcda"

The same letters are at least distance 2 from each other.

Solution

public class Solution {
    public class Occur {
        public char c;
        public int cnt;
        public Occur(char c, int cnt) {this.c = c; this.cnt = cnt;}
    }

    public String rearrangeString(String str, int k) {

        if(k <= 0) return str;

        // sort by occurence
        Map<Character, Integer> map = new HashMap<Character, Integer>();
        for(char c: str.toCharArray()) {
            if(!map.containsKey(c)) map.put(c, 0);
            map.put(c, map.get(c) + 1);
        }

        Queue<Occur> candidate = new PriorityQueue<Occur>(new Comparator<Occur>() {
                public int compare(Occur o1, Occur o2) {
                    return -Integer.compare(o1.cnt, o2.cnt);
                }
            }
        );

        for(Character c: map.keySet()) {
            candidate.offer(new Occur(c, map.get(c)));
        }

        // maintain a window of K to maintain available insert
        boolean inwindow[] = new boolean[128];
        char output[] = new char[str.length()];
        for(int i = 0; i < str.length(); i++) {
            List<Occur> occurList = new ArrayList<Occur>();

            if(i >= k) inwindow[output[i - k]] = false;
            boolean found = false;

            // find a available char
            while(!candidate.isEmpty()) {
                Occur occur = candidate.poll();    

                if(occur.cnt > 0 && !inwindow[occur.c]) {
                    occur.cnt--;
                    inwindow[occur.c] = true;
                    output[i] = occur.c;
                    found = true;

                    if(occur.cnt > 0) occurList.add(occur);
                    break;
                } else {
                    occurList.add(occur);
                }
            }

            if(!found) return "";
            candidate.addAll(occurList);
        }

        return new String(output);
    }
}

results matching ""

    No results matching ""