[LeetCode] Design Compressed String Iterator 設計壓縮字符串的迭代器


 

Design and implement a data structure for a compressed string iterator. It should support the following operations: next and hasNext.

The given compressed string will be in the form of each letter followed by a positive integer representing the number of this letter existing in the original uncompressed string.

next() - if the original string still has uncompressed characters, return the next letter; Otherwise return a white space.
hasNext() - Judge whether there is any letter needs to be uncompressed.

Note:
Please remember to RESET your class variables declared in StringIterator, as static/class variables are persisted across multiple test cases. Please see here for more details.

Example:

StringIterator iterator = new StringIterator("L1e2t1C1o1d1e1");

iterator.next(); // return 'L'
iterator.next(); // return 'e'
iterator.next(); // return 'e'
iterator.next(); // return 't'
iterator.next(); // return 'C'
iterator.next(); // return 'o'
iterator.next(); // return 'd'
iterator.hasNext(); // return true
iterator.next(); // return 'e'
iterator.hasNext(); // return false
iterator.next(); // return ' '

 

這道題給了我們一個壓縮字符串,就是每個字符后面跟上其出現的次數,這里就算只出現一次,后面還是要加上1,那么其實如果當字符串很好有連續字符的時候,壓縮字符串反而要比原字符串長。不過這題的重點不在於壓縮字符串本身,而是讓我們設計一個壓縮字符串的迭代器,那么實際上是要我們根據壓縮字符串來輸出原字符串中的所有字符。那么我們關鍵就是要取出每個字符和其出現的次數,每當調用一次next,次數減1,如果減到0了,我們就要取出下一個字符和其出現的次數。我們要用個私有變量s來保存原字符串,然后用個變量i來記錄當前遍歷到的位置,變量c為當前處理的字符,變量cnt為字符c的當前次數。變量i的初始化為0,指向第一個字符,我們在hasNext()函數中,現將s[i]存入c,然后i自增1,然后我們用while循環取出所有的數字,存入cnt中。在next()函數中,如果hasNext()返回true,那么cnt就自減1,返回c;如果hasNext()返回false,那么字節返回空字符。在hasNext()函數中首先判斷cnt的值,如果大於0,直接返回true,參見代碼如下:

 

解法一:

class StringIterator {
public:
    StringIterator(string compressedString) {
        s = compressedString;
        n = s.size();
        i = 0;
        cnt = 0;
        c = ' ';
    }
    
    char next() {
        if (hasNext()) {
            --cnt;
            return c;
        }
        return ' ';
    }
    
    bool hasNext() {
        if (cnt > 0) return true;
        if (i >= n) return false;
        c = s[i++];
        while (i < n && s[i] >= '0' && s[i] <= '9') {
            cnt = cnt * 10 + s[i++] - '0';
        }
        return true;
    }

private:
    string s;
    int n, i, cnt;
    char c;
};

 

我們可以用C++中的字符流類來處理字符串,寫法非常的簡潔,可以少定義一些變量,在hasNext()函數中,如果cnt為0了,那么我們用字符流類直接讀出下一個字符和次數,然后看是否能讀出大於0的次數來返回真假值,參見代碼如下:

 

解法二:

class StringIterator {
public:
    StringIterator(string compressedString) {
        is = istringstream(compressedString);
        cnt = 0;
        c = ' ';
    }
    
    char next() {
        if (hasNext()) {
            --cnt;
            return c;
        }
        return ' ';
    }
    
    bool hasNext() {
        if (cnt == 0) {
            is >> c >> cnt;
        }
        return cnt > 0;
    }

private:
    istringstream is;
    int cnt;
    char c;
};

 

下面這種解法還是用字符流類,和上面方法不同的地方是,在構建函數中完成了所有字符和次數的拆分,然后字符和其次數組成一個pair,加入一個隊列queue中,這樣我們每次處理的時候就直接去queue中取值就行了,這樣hasNext()函數就變的非常簡潔,只需要判斷隊列queue是否為空即可,參見代碼如下:

 

解法三:

class StringIterator {
public:
    StringIterator(string compressedString) {
        istringstream is(compressedString);
        int cnt = 0;
        char c = ' ';
        while (is >> c >> cnt) {
            q.push({c, cnt});
        }
    }
    
    char next() {
        if (hasNext()) {
            auto &t = q.front();
            if (--t.second == 0) q.pop();
            return t.first;
        }
        return ' ';
    }
    
    bool hasNext() {
        return !q.empty();
    }

private:
    queue<pair<char, int>> q;
};

 

參考資料:

https://discuss.leetcode.com/topic/92098/java-concise-single-queue-solution

https://discuss.leetcode.com/topic/92159/short-solution-of-c-using-stringstream-python-using-re

 

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM