[LeetCode 358] Rearrange String k Distance aPart (Hard**)

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:Frequency Hashtable + Character Valid Index Hashtable (类似计算机CPU处理原理)

  1. 首先求出每个字符frequency 的hash table
  2. 还需要一个int[] characterVsValidIndex, 用于记录当前character在result中的index,应该出现的位置 (必须与前一个相距k distance)。 那么根据当前character在result的位置,可以推算出,下一次该character出现时,必须出现在 currentIndex + k 以后的位置。
  3. 需要一个函数getNextLetter,根据当前的Frequency Hashtable, Character Valid Index Hashtable, 和current index (当前需要添加到result中的字符,在result中的index),来得到当前应该取的字符。
    • 条件:频次最高,且current index > Character Valid Index[current character]. 如果找不到则返回 -1;
    private int getNextLetter (int[] frequency, int[] validIndex, int index) {
        int nextLetterPos = -1;
        int maxPriority = Integer.MIN_VALUE; //用于找当前最高频次
        
        for (int i = 0; i < frequency.length; i++) {
            if (frequency[i] > 0 && frequency[i] >= maxPriority && index >= validIndex [i]) {
                maxPriority = frequency[i];
                nextLetterPos = i;
            }
        }
        
        return nextLetterPos;
    }
  1. 如果找不到字符,返回 -1。那么说明无法rearrange,直接返回空字符串。
  2. 如果找到了字符,那么更新Frequency HashtableCharacter Valid Index Hashtable。并把该字符加入到结果集中。

Code

class Solution {
    public String rearrangeString(String s, int k) {
        if (s == null || s.length () == 0)
            return "";
        
        StringBuilder result = new StringBuilder ();
        
        int[] frequency = new int[26]; 
        int[] validIndex = new int[26];
        
        for (int i = 0; i < s.length (); i++) {
            int currentIndex = s.charAt (i) - 'a';
            frequency[currentIndex] ++;
        }
        
        for (int i = 0; i < s.length (); i++) {
            int nextLetterPos = getNextLetter (frequency, validIndex, result.length ());
            if (nextLetterPos == -1)
                return "";
            
            result.append ((char) (nextLetterPos + 'a'));
            frequency[nextLetterPos] --;
            validIndex[nextLetterPos] += k; 
        }
        
        return result.toString ();
    }
    
    private int getNextLetter (int[] frequency, int[] validIndex, int index) {
        int nextLetterPos = -1;
        int maxPriority = Integer.MIN_VALUE;  //用于找当前最高频次
        
        for (int i = 0; i < frequency.length; i++) {
            if (frequency[i] > 0 && frequency[i] >= maxPriority && index >= validIndex [i]) {
                maxPriority = frequency[i];
                nextLetterPos = i;
            }
        }
        
        return nextLetterPos;
    }
}

你可能感兴趣的:([LeetCode 358] Rearrange String k Distance aPart (Hard**))