[LeetCode 周賽183] 3. 最長快樂字符串(貪心、構造、巧妙解法)

1. 題目來源

鏈接:5195. 最長快樂字符串

2. 題目說明

在這裏插入圖片描述

3. 題目解析

方法一:貪心+構造+巧妙解法

這個問題其實正面考慮比較麻煩的。在此利用貪心的去構造會能直觀簡單點,下面談談構造策略:

  • 首先很直觀的能夠想到,若有多個字符,我們儘可能兩兩的將其放到一起,用另一個字母對其進行間隔。但是這對條件的判斷以及特殊輸入情況來講就很麻煩,一度不知道如何去判斷
  • 換一種構造策略,我們首先不考慮連續輸出兩字符,先考慮輸出一個字符,那麼一定是符合題意並且是最長的,那麼可能會剩餘一些字母,並且肯定已經有部分字母已經被用完了。這樣我們就先構造出了 連續不相同的字符串
  • 接着我們將剩餘字母向字符串進行回填,即若剩餘字母 a,就將字符串中單個的 a 擴充成兩個 a,這樣也是肯定滿足要求的並且還是最長的

即先填一個字符,若字符還有剩餘,那麼就將字符補充爲兩個,這樣一定是合法且最長的。

在此貪心的進行構造,每次嘗試進行構造時肯定是從當前字母個數最多的開始填充,這樣才能構造出最長的連續字符串,一個排序函數就可以了。

在進行回填的時候,循環遍歷字符串,並查看字符串每一位是否還有剩餘字符,若仍存在剩餘字符就填充一個進去,這樣遍歷完畢字符串就是滿足題意的最長字符串了。很秒的思想!

構造方法多種多樣,前幾位大佬真的很快…

參見代碼如下:

// 執行用時 :4 ms, 在所有 C++ 提交中擊敗了100.00%的用戶
// 內存消耗 :6.5 MB, 在所有 C++ 提交中擊敗了100.00%的用戶

int cnt[4], idx[4];
inline bool cmp(int a, int b) {return cnt[a] > cnt[b];}

class Solution {
public:
    char help(int x) {
        if (x == 1) return 'a';
        if (x == 2) return 'b';
        return 'c';
    }
    string longestDiverseString(int a, int b, int c) {
        vector<int> vt; vt.push_back(0);
        cnt[1] = a, cnt[2] = b, cnt[3] = c;
        idx[1] = 1, idx[2] = 2, idx[3] = 3;
        
        bool flag = true;
        while (flag) {
            sort(idx + 1, idx + 4, cmp);
            flag = false;
            for (int i = 1; i <= 3 and flag == false; ++i) {
                int c = idx[i];
                if (vt.back() != c and cnt[c] > 0) {
                    --cnt[c];
                    vt.push_back(c);
                    flag = true;
                }
            }
        }
        
        int len = vt.size();
        string ans = "";
        for (int i = 1; i < len; ++i) {
            ans += help(vt[i]);
            if (cnt[vt[i]] > 0) {
                ans += help(vt[i]);
                --cnt[vt[i]];
            }
        }
        
        return ans;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章