1. 程式人生 > 其它 >[LeetCode] 1286. Iterator for Combination 字母組合迭代器

[LeetCode] 1286. Iterator for Combination 字母組合迭代器


Design theCombinationIteratorclass:

  • CombinationIterator(string characters, int combinationLength)Initializes the object with a stringcharactersofsorted distinctlowercase English letters and a numbercombinationLengthas arguments.
  • next()Returns the next combination of lengthcombinationLengthinlexicographical order.
  • hasNext()Returnstrueif and only if there exists a next combination.

Example 1:

Input
["CombinationIterator", "next", "hasNext", "next", "hasNext", "next", "hasNext"]
[["abc", 2], [], [], [], [], [], []]
Output
[null, "ab", true, "ac", true, "bc", false]

Explanation
CombinationIterator itr = new CombinationIterator("abc", 2);
itr.next();    // return "ab"
itr.hasNext(); // return True
itr.next();    // return "ac"
itr.hasNext(); // return True
itr.next();    // return "bc"
itr.hasNext(); // return False

Constraints:

  • 1 <= combinationLength <= characters.length <= 15
  • All the characters ofcharactersareunique.
  • At most104calls will be made tonextandhasNext.
  • It is guaranteed that all calls of the functionnextare valid.

這道題讓設計一個 CombinationIterator 類,初始化時給一個有序的字串,然後一個組合的長度,有兩個成員函式,一個是 next() 函式,是返回下一個按字母順序,且是給定長度的組合,另一個 hasNext() 函式用來判斷是否還存在下一個組合。給的例子可以很好的幫助我們理解題意,比如給的字串是 "abc",返回組合的長度是2的話,則就是按照字母順序來返回組合,"ab", "ac", "bc"。其實本質就是找出給定長度的所有組合,就拿給的例子 "abc" 來說吧,找出兩個字母的組合,就是在三個字母中任意選兩個,如果用1表示選擇該字母,0表示不選的話,就有如下種情況:

a b c
0 0 0 -> ""
0 0 1 -> c
0 1 0 -> b
0 1 1 -> bc
1 0 0 -> a
1 0 1 -> ac
1 1 0 -> ab
1 1 1 -> abc

而每種情況正好對應一個二進位制數,有三個字母的話,子集總個數為 2^3 = 8 個,每一種可以用一個二進位制 mask 來表示,目標就是找出長度為2的組合。至於字母順序不用太擔心,將所有找出的組合放到一個 TreeSet 中,利用其自動排序的功能就行了。所以 mask 從1遍歷到 2^n(這裡的n為3),然後遍歷給定字串的長度,去看 mask 對應位上是1還是0,為1的話就將對應位的字母加到t中,最後看t的長度是多少,若是2的話,就加到 TreeSet 中。等將所有的長度為2的組合就找出來加到 TreeSet 中了之後,next 和 hasNext 函式就非常好實現了,用一個 iterator 就行了,next 就是看迭代器是否到末尾了,是的話返回空,否則返回當前指向到元素,並且迭代器後移一位。hasNext 就看迭代器是否到末尾了就行了,參見程式碼如下:


解法一:

class CombinationIterator {
public:
    CombinationIterator(string characters, int combinationLength) {
        st = generateAll(characters, combinationLength);
        cur = begin(st);
    }    
    string next() {
        return cur == end(st) ? "" : *cur++;
    }    
    bool hasNext() {
        return cur != end(st);
    }

private:
    set<string> st;
    set<string>::iterator cur;
    
    set<string> generateAll(string str, int len) {
        set<string> res;
        int n = 1 << str.size();
        for (int mask = 1; mask < n; ++mask) {
            string t = "";
            for (int i = 0; i < str.size(); ++i) {
                if (mask & (1 << i)) t += str[i];
            }
            if (t.size() == len) res.insert(t);
        }
        return res;
    }
};

我們也可以用迭代的方法來找出所有的組合,寫法能稍微簡潔一些,遞迴函式 generateAll 需要多加兩個引數,start 和 res,分別是當前遍歷到的位置,而當前組成的字串。在遞迴函式中,若 len 為0了,則表示找到所求長度的組合,將其加入 TreeSet 中,否則就從 start 遍歷到 n-len,然後呼叫遞迴函式,此時代入 len-1,i+1,和 res+str[i] 作為引數即可,參見程式碼如下:


解法二:

class CombinationIterator {
public:
    CombinationIterator(string characters, int combinationLength) {
        generateAll(characters, combinationLength, 0, "");
        cur = begin(st);
    }    
    string next() {
        return cur == end(st) ? "" : *cur++;
    }    
    bool hasNext() {
        return cur != end(st);
    }

private:
    set<string> st;
    set<string>::iterator cur;
    
    void generateAll(string str, int len, int start, string res) {
        if (len == 0) {
            st.insert(res);
            return;
        }
        for (int i = start; i <= (int)str.size() - len; ++i) {
            generateAll(str, len - 1, i + 1, res + str[i]);
        }
    }
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/1286


參考資料:

https://leetcode.com/problems/iterator-for-combination/

https://leetcode.com/problems/iterator-for-combination/discuss/451322/(JAVA)-Generate-Combinations

https://leetcode.com/problems/iterator-for-combination/discuss/451368/C%2B%2B-solution-with-multiple-pointers

https://leetcode.com/problems/iterator-for-combination/discuss/789164/C%2B%2B-Using-Bit-manipulation-or-Detail-Explain


LeetCode All in One 題目講解彙總(持續更新中...)


喜歡請點贊,疼愛請打賞❤️~.~


微信打賞


Venmo 打賞