1. 程式人生 > 實用技巧 >letcode每日一題-重構字串

letcode每日一題-重構字串

週末去了動物園,雖然我幾乎被凍成了狗,但還是好開心呀,今天開開心心的來更新啦!!!

題目描述:

方法:基於最大堆的貪心演算法
維護最大堆儲存字母,堆頂元素為出現次數最多的字母。首先統計每個字母的出現次數,然後將出現次數大於 00 的字母加入最大堆。

當最大堆的元素個數大於 11 時,每次從最大堆取出兩個字母,拼接到重構的字串,然後將兩個字母的出現次數分別減 11,並將剩餘出現次數大於 00 的字母重新加入最大堆。由於最大堆中的元素都是不同的,因此取出的兩個字母一定也是不同的,將兩個不同的字母拼接到重構的字串,可以確保相鄰的字母都不相同。

如果最大堆變成空,則已經完成字串的重構。如果最大堆剩下 11 個元素,則取出最後一個字母,拼接到重構的字串。

對於長度為 nn 的字串,共有 n/2n/2 次每次從最大堆取出兩個字母的操作,當 nn 是奇數時,還有一次從最大堆取出一個字母的操作,因此重構的字串的長度一定是 nn。

當 nn 是奇數時,是否可能出現重構的字串的最後兩個字母相同的情況?如果最後一個字母在整個字串中至少出現了 22 次,則在最後一次從最大堆取出兩個字母時,該字母會先被選出,因此不會成為重構的字串的倒數第二個字母,也不可能出現重構的字串最後兩個字母相同的情況。

因此,在重構字串可行的情況下,基於最大堆的貪心演算法可以確保得到正確答案。
實現程式碼如下:


public String reorganizeString(String S) {
        int[] charCount=new int[26];
        //統計字元出現的次數
        for(int i=0;i<S.length();i++){
            int index=S.charAt(i)-'a';
            charCount[index]++;
        }
        //建立一個從大到小排序的佇列
        PriorityQueue<Character> queue=new PriorityQueue<>((o1,o2)->{
            if(charCount[o1-'a']>charCount[o2-'a']){
                return -1;
            }
            if(charCount[o1-'a']<charCount[o2-'a']){
                return 1;
            }
            return 0;
        });
        //把字元放進佇列中
        for(int i=0;i<charCount.length;i++){
            if(charCount[i]!=0){
                queue.offer((char)(i+'a'));
            }
        }
        StringBuilder result=new StringBuilder();
        while (queue.size()>1){
            //出現頻率最高的字元
            char max_count_char=queue.poll();
            //出現頻率第二高的字元
            char second_count_char=queue.poll();
            int maxIndex=max_count_char-'a';
            int secondIndex=second_count_char-'a';
            //重新構建字串
            if(result.length()==0 || result.charAt(result.length()-1)!=max_count_char){
                result.append(max_count_char);
                charCount[maxIndex]--;
            }
            int minLen=Math.min(charCount[maxIndex],charCount[secondIndex]);
            for(int i=0;i<minLen;i++){
                result.append(second_count_char).append(max_count_char);
            }
            //--重新構建字串結束
            charCount[maxIndex]-=minLen;
            charCount[secondIndex]-=minLen;
            if(charCount[maxIndex]>0){
                queue.offer(max_count_char);
            }
            if (charCount[secondIndex]>0){
                queue.offer(second_count_char);
            }
        }
        if(queue.size()==0){
            return result.toString();
        }
        if(queue.size()==1){
            char last=queue.poll();
            if(charCount[last-'a']==1 && result.charAt(result.length()-1)!=last){
                result.append(last);
                return result.toString();
            }
        }
        return "";
    }