[LeetCode] 880. Decoded String at Index 在位置坐標處解碼字符串



An encoded string `S` is given.  To find and write the *decoded* string to a tape, the encoded string is read one character at a time and the following steps are taken:
  • If the character read is a letter, that letter is written onto the tape.
  • If the character read is a digit (say d), the entire current tape is repeatedly written d-1 more times in total.

Now for some encoded string S, and an index K, find and return the K-th letter (1 indexed) in the decoded string.

Example 1:

Input: S = "leet2code3", K = 10
Output: "o"
Explanation:
The decoded string is "leetleetcodeleetleetcodeleetleetcode".
The 10th letter in the string is "o".

Example 2:

Input: S = "ha22", K = 5
Output: "h"
Explanation:
The decoded string is "hahahaha".  The 5th letter is "h".

Example 3:

Input: S = "a2345678999999999999999", K = 1
Output: "a"
Explanation:
The decoded string is "a" repeated 8301530446056247680 times.  The 1st letter is "a".

Note:

  1. 2 <= S.length <= 100
  2. S will only contain lowercase letters and digits 2through 9.
  3. S starts with a letter.
  4. 1 <= K <= 10^9
  5. The decoded string is guaranteed to have less than 2^63 letters.

這道題給了我們一個加碼后的字符串,其實就是一種特殊的壓縮方式,里面的數字代表前面所有的字符串重復的次數,又給了一個坐標K,讓我們返回還原后的字符串中K位置的子串,其實就是一個字符,但是返回類型非要是字符串。博主最開始做的時候,沒有認真讀題,將壓縮方式搞錯了兩個地方,首先博主以為多個數字相連的話要拼成個多位數,但實際上是分開的,比如例子2中的 ha22,第一個2是將 ha 重復兩次,第二個2是將 haha 重復兩次。博主犯的另一個錯誤是以為只重復之前的字符串部分,比如 a2b3,博主以為后面的3只是將b重復三次,其實是將前面的 a2b 重復三次。不認真審題的代價是慘重的,被 OJ 批的體無完膚。現在既然已經弄清楚了題意,就來想想如何解題吧。這道題是主要是參考了[大神lee215的帖子](https://leetcode.com/problems/decoded-string-at-index/discuss/156747/C%2B%2BPython-O(N)-Time-O(1)-Space),現在很少能看到史蒂芬大神的帖子了,在后史蒂芬時代,lee215 大神獨自撐起了一片天空,有時候題既是大神出的,最高分解法還是大神寫的,不得不使人無比崇敬。

怒吹一波后回到題目,大家最容易想到的方法就是直接按規律還原字符串唄,將還原后的字符串保存出來,這樣就可以利用K來直接訪問了。這種方法博主連試都不願意試的,OJ 是有尊嚴的,不甩你個 Time Limited Exceeded,也得來個 Memory Limited Exceeded 吧。保存解碼后的整個字符串是不現實的,但是我們又必須要知道原字符串的坐標信息,那么唯一的選擇就是記錄解碼后字符串的長度,比如 ha22,當遍歷到a的時候,此時計數器為2,表示當前解碼到的位置長度為2,當遇到第一個2的時候,用當前的計數器的值乘以這個數字,即 2x2=4,說明此時解碼后的字符串長度為4,當再遍歷到最后一個2的時候,同樣的操作,用當前計數器的值乘以這個數字,即 4x2=8,則最終的解碼后的字符串長度為8。這種操作是可以統計出解碼后字符串的長度的,但是我們沒有必要統計整個的長度,因為題目只讓找第K個位置的字符,那么我們只需要解碼到計數器 cnt 剛好大於等於K的時候就可以停止了。當 cnt 大於等於 K 的時候,現在的i位置不一定是所求,我們得往前找,找到那個符合題意的第K個字符。所以需要從i位置往前遍歷,當 S[i] 是數字的時候,此時的處理就是跟之前反過來了,之前我們遇到數字,都是乘以計數器 cnt,此時我們應該用計數器除以這個數字,同時K應該對縮小后的 cnt 取余。還是拿例子2來說,當遍歷完最后一個2時,此時計數器為8,大於 K=5 了,所以需要往前遍歷,那么 cnt 除以2之后變為了4,此時用K對4取余,得到1。然后再往前遍歷,還是2,用 cnt 除以2之后變為了2,此時 K=1 對2取余,還是1。此時再往前,遍歷到字母a,此時發現 K=1 不能整除 cnt=2,則 cnt 自減1,因為還要往前走。那么當到達字母h時,此時 K=1 終於可以整除 cnt=1 了,則當前的 S[i] 即為所求,參見代碼如下:


解法一:
class Solution {
public:
    string decodeAtIndex(string S, int K) {
        long i = 0, cnt = 0;
        for (; cnt < K; ++i) {
            cnt = isdigit(S[i]) ? cnt * (S[i] - '0') : (cnt + 1);
        }
        while (i--) {
            if (isdigit(S[i])) {
                cnt /= (S[i] - '0');
                K %= cnt;
            } else {
                if (K % cnt == 0) return string(1, S[i]);
                --cnt;
            }
        }
        return "grandyang";
    }
};

我們也可以使用遞歸來做,其實思路都是一樣的,還是需要一個長整型的計數器 cnt,然后遍歷原字符串S,當 S[i] 是字母的時候,且自增1后的 cnt 等於K了,說明正好找了第K個字符,直接轉為字符串返回即可。否則遇到數字的話,還是要乘以計數器 cnt,若大於等於K的話,則調用遞歸函數,注意這里的S可以用 [0, i) 之間的子串代替,可以省些空間,當然用S也是可以的。K的話比較 tricky,因為這里 cnt 乘以了一個數字(大於1)才能大於等於K,所以當前的 cnt 一定是小於K的,那么此時就有 cnt 是否能整除K兩種情況,當 cnt 不能整除K時,比如當 cnt=2,K=5 時,就是例子2中的情況,我們用K對 cnt 取余,得到1來帶入遞歸。但是當 cnt 可以整除K時,比如當 cnt=2,K=4 時,若直接取余,會得到0,直接帶入0肯定時不對的,因為題目中說了K是從1開始的,所以我們應該帶入的是 cnt 本身,那么兩種情況合為一個表達式就是 (K-1)%cnt + 1。若 cnt 小於K,則乘以當前數字即可,參見代碼如下:
解法二:
class Solution {
public:
    string decodeAtIndex(string S, int K) {
        long cnt = 0;
        for (int i = 0; i < S.size(); ++i) {
            if (isalpha(S[i])) {
                if (++cnt == K) return string(1, S[i]);
            } else {
                if (cnt * (S[i] - '0') >= K) return decodeAtIndex(S.substr(0, i), (K - 1) % cnt + 1);
                cnt *= (S[i] - '0');
            }
        }
        return "grandyang";
    }
};

Github 同步地址:

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


參考資料:

https://leetcode.com/problems/decoded-string-at-index/

https://leetcode.com/problems/decoded-string-at-index/discuss/157156/15-lines-clear-code

https://leetcode.com/problems/decoded-string-at-index/discuss/156747/C%2B%2BPython-O(N)-Time-O(1)-Space


[LeetCode All in One 題目講解匯總(持續更新中...)](https://www.cnblogs.com/grandyang/p/4606334.html)


免責聲明!

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



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