0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

LeetCode 394:字符串解碼

算法與數(shù)據(jù)結(jié)構(gòu) ? 來(lái)源:吳師兄學(xué)算法 ? 作者:吳師兄學(xué)算法 ? 2022-08-31 15:57 ? 次閱讀

今天的題目來(lái)源于 LeetCode 第 394 號(hào)問題:字符串編碼,難度為「中等」,根據(jù)評(píng)論區(qū)的反饋,近期華為面試、字節(jié)面試都出現(xiàn)過。

0a45d7d4-28dd-11ed-ba43-dac502259ad0.png0a61357e-28dd-11ed-ba43-dac502259ad0.png

一、題目描述

給定一個(gè)經(jīng)過編碼的字符串,返回它解碼后的字符串。

編碼規(guī)則為:k[encoded_string],表示其中方括號(hào)內(nèi)部的encoded_string正好重復(fù)k次。注意k保證為正整數(shù)。

你可以認(rèn)為輸入字符串總是有效的;輸入字符串中沒有額外的空格,且輸入的方括號(hào)總是符合格式要求的。

此外,你可以認(rèn)為原始數(shù)據(jù)不包含數(shù)字,所有的數(shù)字只表示重復(fù)的次數(shù)k,例如不會(huì)出現(xiàn)像3a2[4]的輸入。

示例 1:

輸入:s ="3[a]2[bc]"
輸出:"aaabcbc"

示例 2:

輸入:s ="3[a2[c]]"
輸出:"accaccacc"

示例 3:

輸入:s ="2[abc]3[cd]ef"
輸出:"abcabccdcdcdef"

示例 4:

輸入:s ="abc3[cd]xyz"
輸出:"abccdcdcdxyz"

提示:

  • 1 <= s.length <= 30
  • s由小寫英文字母、數(shù)字和方括號(hào)'[]'組成
  • s保證是一個(gè)有效的輸入。
  • s中所有整數(shù)的取值范圍為[1, 300]

二、題目解析

注意示例 2 ,可以發(fā)現(xiàn)字符串中存在括號(hào)內(nèi)有嵌套括號(hào)的情況,這個(gè)時(shí)候,只有先把內(nèi)層括號(hào)解碼成功,才能再去解碼外層括號(hào)。

0a7d0254-28dd-11ed-ba43-dac502259ad0.png

也就意味著后面訪問的括號(hào)比前面訪問的括號(hào)還更早的進(jìn)行處理,與棧的先入后出特點(diǎn)對(duì)應(yīng)。

所以,本題使用棧來(lái)處理。

具體操作如下:

1、構(gòu)建兩個(gè)棧,一個(gè)是數(shù)字棧numStack,在遍歷編碼字符串過程中記錄出現(xiàn)的數(shù)字;一個(gè)是字符串棧strStack,在遍歷編碼字符串過程中記錄出現(xiàn)的字符串。

2、初始化兩個(gè)變量,一個(gè)是digit,用來(lái)記錄訪問到字符串之前出現(xiàn)的數(shù)字;一個(gè)是res,在訪問編碼字符串的過程中,把得到的結(jié)果存放到 res 中。

3、接下來(lái),開始從頭到尾訪問編碼字符串,在訪問過程中,字符會(huì)出現(xiàn) 4 種情況。

0a9739d0-28dd-11ed-ba43-dac502259ad0.png

4、如果是數(shù)字,需要把字符轉(zhuǎn)成整型數(shù)字,然后更新到digit上,代表后續(xù)的字符串需要重復(fù)digit次。

5、如果是字符,說(shuō)明它就出現(xiàn)一次,可以直接存放到 res 中。

6、如果是"[" ,這個(gè)時(shí)候出現(xiàn)了嵌套的內(nèi)層編碼字符串,而外層的解碼需要等待內(nèi)層解碼的結(jié)果,那么之前已經(jīng)掃描的字符需要存放起來(lái),等到內(nèi)層解碼之后再重新使用。

0ab9202c-28dd-11ed-ba43-dac502259ad0.png

7、如果是"]" ,此時(shí),內(nèi)層解碼已經(jīng)有結(jié)果,需要把它和前面的字符串進(jìn)行拼接。

8、拼接的方式就是先通過 numsStack 的棧頂元素獲取重復(fù)的次數(shù),再通過 strStack 的棧頂元素獲取前面的字符串。

9、最后返回 res 就行。

三、參考代碼

1、Java 代碼

//登錄AlgoMooc官網(wǎng)獲取更多算法圖解
//https://www.algomooc.com
//作者:程序員吳師兄
//代碼有看不懂的地方一定要私聊咨詢吳師兄呀
//字符串解碼(LeetCode394)//leetcode.cn/problems/decode-string/
classSolution{
publicStringdecodeString(Strings){

//創(chuàng)建數(shù)字棧,在遍歷編碼字符串過程中記錄出現(xiàn)的數(shù)字
DequenumStack=newLinkedList<>();

//創(chuàng)建字符棧,在遍歷編碼字符串過程中記錄出現(xiàn)的字符串
DequestrStack=newLinkedList<>();

//在訪問編碼字符串的過程中,用來(lái)記錄訪問到字符串之前出現(xiàn)的數(shù)字,一開始為0
intdigit=0;

//在訪問編碼字符串的過程中,把得到的結(jié)果存放到res中
StringBuilderres=newStringBuilder();

//從頭到尾遍歷編碼字符串
for(inti=0;i//在遍歷過程中,字符會(huì)出現(xiàn)4種情況

//先獲取此時(shí)訪問的字符
charch=s.charAt(i);

//1、如果是數(shù)字,需要把字符轉(zhuǎn)成整型數(shù)字
//注意數(shù)字不一定是1位,有可能是多位
//比如123a,在字母a的前面出現(xiàn)了123,表示a重復(fù)出現(xiàn)123次
//那么一開始ch為1,當(dāng)訪問到ch為2的時(shí)候,1和2要組成數(shù)字12
//再出現(xiàn)3,12和3組成數(shù)字123
if(Character.isDigit(ch)){

//先將字符轉(zhuǎn)成整型數(shù)字ch-‘0’
//補(bǔ)充知識(shí):將字符'0'-'9'轉(zhuǎn)換為數(shù)字,只需將字符變量減去'0'就行
//因?yàn)樽址蛿?shù)字在內(nèi)存里都是以ASCII碼形式存儲(chǔ)的
//減去'0',其實(shí)就是減去字符'0'的ASCII碼,而字符'0'的ASCII碼是30
//所以減去'0'也就是減去30,然后就可以得到字符對(duì)應(yīng)的數(shù)字了。
intnum=ch-'0';

//再將這個(gè)數(shù)字和前面存儲(chǔ)的數(shù)字進(jìn)行組合
//1和2組成數(shù)字12,也就是1*10+2=12
//12和3組成數(shù)字123,也就是12*10+3=123
digit=digit*10+num;

//2、如果是字符
}elseif((ch>='a'&&ch<=?'z')){

//說(shuō)明它就出現(xiàn)一次,可以直接存放到res中
res.append(ch);

//3、如果是"["
//出現(xiàn)了嵌套的內(nèi)層編碼字符串,而外層的解碼需要等待內(nèi)層解碼的結(jié)果
//那么之前已經(jīng)掃描的字符需要存放起來(lái),等到內(nèi)層解碼之后再重新使用
}elseif(ch=='['){

//把數(shù)字存放到數(shù)字棧
numStack.push(digit);

//把外層的解碼字符串存放到字符串棧
strStack.push(res);

//開始新的一輪解碼
//于是,digit歸零
digit=0;

//res重新初始化
res=newStringBuilder();

//4、如果是"]"
}elseif(ch==']'){

//此時(shí),內(nèi)層解碼已經(jīng)有結(jié)果,需要把它和前面的字符串進(jìn)行拼接

//第一步,先去查看內(nèi)層解碼的字符串需要被重復(fù)輸出幾次
//比如e3[abc],比如內(nèi)層解碼結(jié)果abc需要輸出3次
//通過數(shù)字棧提取出次數(shù)
intcount=numStack.poll();

//第二步,通過字符串棧提取出之前的解碼字符串
StringBuilderoutString=strStack.poll();

//第三步,不斷的把內(nèi)層解碼的字符串拼接起來(lái)
for(intj=0;j//拼接到outString后面,拼接count次
outString.append(res.toString());
}

//再把此時(shí)得到的結(jié)果賦值給res
res=outString;
}
}

//返回解碼成功的字符串
returnres.toString();
}
}

2、C++ 代碼

classSolution{
public:
stringdecodeString(strings){
//創(chuàng)建數(shù)字棧,在遍歷編碼字符串過程中記錄出現(xiàn)的數(shù)字
stack<int>numStack;

//創(chuàng)建字符棧,在遍歷編碼字符串過程中記錄出現(xiàn)的字符串
stack<string>strStack;

//在訪問編碼字符串的過程中,用來(lái)記錄訪問到字符串之前出現(xiàn)的數(shù)字,一開始為0
intdigit=0;

//在訪問編碼字符串的過程中,把得到的結(jié)果存放到res中
stringres;

//從頭到尾遍歷編碼字符串
for(inti=0;i//在遍歷過程中,字符會(huì)出現(xiàn)4種情況

//先獲取此時(shí)訪問的字符
charch=s[i];
//1、如果是數(shù)字,需要把字符轉(zhuǎn)成整型數(shù)字
//注意數(shù)字不一定是1位,有可能是多位
//比如123a,在字母a的前面出現(xiàn)了123,表示a重復(fù)出現(xiàn)123次
//那么一開始ch為1,當(dāng)訪問到ch為2的時(shí)候,1和2要組成數(shù)字12
//再出現(xiàn)3,12和3組成數(shù)字123
if(ch>='0'&&ch<='9'){

//先將字符轉(zhuǎn)成整型數(shù)字ch-‘0’
//補(bǔ)充知識(shí):將字符'0'-'9'轉(zhuǎn)換為數(shù)字,只需將字符變量減去'0'就行
//因?yàn)樽址蛿?shù)字在內(nèi)存里都是以ASCII碼形式存儲(chǔ)的
//減去'0',其實(shí)就是減去字符'0'的ASCII碼,而字符'0'的ASCII碼是30
//所以減去'0'也就是減去30,然后就可以得到字符對(duì)應(yīng)的數(shù)字了。
intnum=ch-'0';

//再將這個(gè)數(shù)字和前面存儲(chǔ)的數(shù)字進(jìn)行組合
//1和2組成數(shù)字12,也就是1*10+2=12
//12和3組成數(shù)字123,也就是12*10+3=123
digit=digit*10+num;

//2、如果是字符
}elseif((ch>='a'&&ch<=?'z')){

//說(shuō)明它就出現(xiàn)一次,可以直接存放到res中
res+=ch;

//3、如果是"["
//出現(xiàn)了嵌套的內(nèi)層編碼字符串,而外層的解碼需要等待內(nèi)層解碼的結(jié)果
//那么之前已經(jīng)掃描的字符需要存放起來(lái),等到內(nèi)層解碼之后再重新使用
}elseif(ch=='['){

//把數(shù)字存放到數(shù)字棧
numStack.push(digit);

//把外層的解碼字符串存放到字符串棧
strStack.push(res);

//開始新的一輪解碼
//于是,digit歸零
digit=0;

//res重新初始化
res="";

//4、如果是"]"
}elseif(ch==']'){

//此時(shí),內(nèi)層解碼已經(jīng)有結(jié)果,需要把它和前面的字符串進(jìn)行拼接

//第一步,先去查看內(nèi)層解碼的字符串需要被重復(fù)輸出幾次
//比如e3[abc],比如內(nèi)層解碼結(jié)果abc需要輸出3次
//通過數(shù)字棧提取出次數(shù)
intcount=numStack.top();

numStack.pop();

//第二步,通過字符串棧提取出之前的解碼字符串
stringoutString=strStack.top();

strStack.pop();

//第三步,不斷的把內(nèi)層解碼的字符串拼接起來(lái)
for(intj=0;j//拼接到outString后面,拼接count次
outString+=res;
}

//再把此時(shí)得到的結(jié)果賦值給res
res=outString;
}
}

//返回解碼成功的字符串
returnres;
}
};

3、Python 代碼

classSolution:
defdecodeString(self,s:str)->str:
#創(chuàng)建數(shù)字棧,在遍歷編碼字符串過程中記錄出現(xiàn)的數(shù)字
numStack=[]

#創(chuàng)建字符棧,在遍歷編碼字符串過程中記錄出現(xiàn)的字符串
strStack=[]

#在訪問編碼字符串的過程中,用來(lái)記錄訪問到字符串之前出現(xiàn)的數(shù)字,一開始為0
digit=0

#在訪問編碼字符串的過程中,把得到的結(jié)果存放到res中
res=""

#從頭到尾遍歷編碼字符串
forchins:

#在遍歷過程中,字符會(huì)出現(xiàn)4種情況
#先獲取此時(shí)訪問的字符
#1、如果是數(shù)字,需要把字符轉(zhuǎn)成整型數(shù)字
#注意數(shù)字不一定是1位,有可能是多位
#比如123a,在字母a的前面出現(xiàn)了123,表示a重復(fù)出現(xiàn)123次
#那么一開始ch為1,當(dāng)訪問到ch為2的時(shí)候,1和2要組成數(shù)字12
#再出現(xiàn)3,12和3組成數(shù)字123
if'0'<=?ch?<=?'9':

#先將字符轉(zhuǎn)成整型數(shù)字ch-‘0’
#補(bǔ)充知識(shí):將字符'0'-'9'轉(zhuǎn)換為數(shù)字,只需將字符變量減去'0'就行
#因?yàn)樽址蛿?shù)字在內(nèi)存里都是以ASCII碼形式存儲(chǔ)的
#減去'0',其實(shí)就是減去字符'0'的ASCII碼,而字符'0'的ASCII碼是30
#所以減去'0'也就是減去30,然后就可以得到字符對(duì)應(yīng)的數(shù)字了。
num=int(ch)

#再將這個(gè)數(shù)字和前面存儲(chǔ)的數(shù)字進(jìn)行組合
#1和2組成數(shù)字12,也就是1*10+2=12
#12和3組成數(shù)字123,也就是12*10+3=123
digit=digit*10+num

#2、如果是字符
elifch>='a'andch<=?'z':

#說(shuō)明它就出現(xiàn)一次,可以直接存放到res中
res+=ch

#3、如果是"["
#出現(xiàn)了嵌套的內(nèi)層編碼字符串,而外層的解碼需要等待內(nèi)層解碼的結(jié)果
#那么之前已經(jīng)掃描的字符需要存放起來(lái),等到內(nèi)層解碼之后再重新使用
elifch=='[':

#把數(shù)字存放到數(shù)字棧
numStack.append(digit)

#把外層的解碼字符串存放到字符串棧
strStack.append(res)

#開始新的一輪解碼
#于是,digit歸零
digit=0

#res重新初始化
res=""

#4、如果是"]"
elifch==']':

#此時(shí),內(nèi)層解碼已經(jīng)有結(jié)果,需要把它和前面的字符串進(jìn)行拼接

#第一步,先去查看內(nèi)層解碼的字符串需要被重復(fù)輸出幾次
#比如e3[abc],比如內(nèi)層解碼結(jié)果abc需要輸出3次
#通過數(shù)字棧提取出次數(shù)
count=numStack.pop()

#第二步,通過字符串棧提取出之前的解碼字符串
outString=strStack.pop()

#第三步,不斷的把內(nèi)層解碼的字符串拼接起來(lái)
forjinrange(0,count):
#拼接到outString后面,拼接count次
outString+=res


#再把此時(shí)得到的結(jié)果賦值給res
res=outString

#返回解碼成功的字符串
returnres

四、復(fù)雜度分析

  • 時(shí)間復(fù)雜度 O(N),一次遍歷s
  • 空間復(fù)雜度 O(N),輔助棧在極端情況下需要線性空間。

審核編輯 :李倩


聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 解碼
    +關(guān)注

    關(guān)注

    0

    文章

    175

    瀏覽量

    27286
  • 字符串
    +關(guān)注

    關(guān)注

    1

    文章

    566

    瀏覽量

    20384

原文標(biāo)題:LeetCode 394:字符串解碼

文章出處:【微信號(hào):TheAlgorithm,微信公眾號(hào):算法與數(shù)據(jù)結(jié)構(gòu)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    labview字符串如何轉(zhuǎn)換為16進(jìn)制字符串

    在LabVIEW中,將字符串轉(zhuǎn)換為16進(jìn)制字符串是一個(gè)常見的需求,尤其是在處理數(shù)據(jù)通信和硬件接口時(shí)。LabVIEW提供了多種方法來(lái)實(shí)現(xiàn)這一轉(zhuǎn)換,包括使用內(nèi)置函數(shù)、編寫VI(Virtual
    的頭像 發(fā)表于 09-04 15:54 ?412次閱讀

    labview中常用的字符串函數(shù)有哪些?

    在LabVIEW中,常用的字符串函數(shù)廣泛覆蓋了對(duì)字符串的各種操作,包括但不限于格式化、搜索、替換、連接、計(jì)算長(zhǎng)度等。以下是一些常用的字符串函數(shù)及其簡(jiǎn)要說(shuō)明: 字符串長(zhǎng)度(String
    的頭像 發(fā)表于 09-04 15:43 ?136次閱讀

    labview字符串的四種表示各有什么特點(diǎn)

    。在LabVIEW中,字符串是一種基本的數(shù)據(jù)類型,用于表示文本信息。字符串在LabVIEW中有多種表示方式,每種方式都有其特定的應(yīng)用場(chǎng)景和特點(diǎn)。以下是對(duì)LabVIEW中四種字符串表示方式的分析: 1.
    的頭像 發(fā)表于 09-04 15:40 ?136次閱讀

    C語(yǔ)言字符串編譯函數(shù)介紹

    在C語(yǔ)言中,字符串實(shí)際上是使用null字符O'終止的一維字符數(shù)組。因此,一個(gè)以null結(jié)尾的字符串,包含了組成字符串
    的頭像 發(fā)表于 03-07 16:18 ?386次閱讀
    C語(yǔ)言<b class='flag-5'>字符串</b>編譯函數(shù)介紹

    labview掃描字符串怎么用

    LabVIEW 是一種流程化編程語(yǔ)言和開發(fā)環(huán)境,主要用于控制、測(cè)量和監(jiān)測(cè)系統(tǒng)。在 LabVIEW 中,掃描字符串是一項(xiàng)常見的任務(wù),它允許用戶按照一定的模式從輸入字符串中提取所需的信息。下面我將詳細(xì)
    的頭像 發(fā)表于 12-29 10:12 ?1501次閱讀

    labview掃描字符串怎么用

    LabVIEW是一種圖形化編程語(yǔ)言,用于開發(fā)控制、測(cè)量和監(jiān)控系統(tǒng)。雖然它主要用于工程和科學(xué)領(lǐng)域,但也可以用于處理文本和字符串。 在LabVIEW中,可以使用字符串處理函數(shù)來(lái)掃描字符串。以下是一些常用
    的頭像 發(fā)表于 12-26 16:58 ?1442次閱讀

    labview中怎么對(duì)字符串中的進(jìn)行實(shí)時(shí)處理

    LabVIEW是一種用于開發(fā)控制、測(cè)試和測(cè)量系統(tǒng)的可視化編程環(huán)境,它提供了許多處理字符串的功能。在LabVIEW中,可以使用不同的函數(shù)和工具來(lái)實(shí)時(shí)處理字符串。下面我將詳細(xì)介紹一些常見的方法和技術(shù)
    的頭像 發(fā)表于 12-26 14:12 ?1276次閱讀

    oracle字符串split成多個(gè)

    Oracle是一種廣泛使用的關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng),它提供了許多強(qiáng)大的功能和函數(shù),用于處理和操作數(shù)據(jù)。其中之一就是字符串分割(split)方法,該方法用于將一個(gè)字符串按照指定的分隔符分割成多個(gè)子字符串
    的頭像 發(fā)表于 12-06 09:54 ?4212次閱讀

    oracle中拼接字符串函數(shù)

    在Oracle中,我們可以使用 CONCAT 函數(shù)來(lái)拼接字符串。CONCAT 函數(shù)接受兩個(gè)參數(shù),它將這兩個(gè)參數(shù)連接起來(lái)并返回相應(yīng)的字符串結(jié)果。 語(yǔ)法示例: CONCAT(string1
    的頭像 發(fā)表于 12-06 09:49 ?2349次閱讀

    字符數(shù)組和字符串有沒有區(qū)別?

    字符數(shù)組和字符串有沒有區(qū)別?
    的頭像 發(fā)表于 11-30 16:39 ?484次閱讀

    MySQL替換字符串函數(shù)REPLACE

    MySQL是目前非常流行的開源數(shù)據(jù)庫(kù)管理系統(tǒng)之一,它具有強(qiáng)大的功能和性能。其中之一的字符串函數(shù)REPLACE,可以用于替換字符串中的指定字符字符串。在本文中,我們將詳細(xì)討論MySQL
    的頭像 發(fā)表于 11-30 10:44 ?1249次閱讀

    c語(yǔ)言字符串定義

    C語(yǔ)言是一種強(qiáng)大而廣泛使用的編程語(yǔ)言,字符串是其中一個(gè)非常重要的概念。在C語(yǔ)言中,字符串是由一系列字符組成的數(shù)組,它可以表示文本、數(shù)字等各種類型的數(shù)據(jù)。在本文中,我們將詳盡、詳實(shí)、細(xì)致地介紹C語(yǔ)言
    的頭像 發(fā)表于 11-24 10:02 ?1423次閱讀

    字符串如何轉(zhuǎn)換成日期型

    隨著計(jì)算機(jī)技術(shù)的不斷發(fā)展,我們經(jīng)常遇到需要處理日期的情況。在編程中,字符串是最常見的日期輸入格式,在許多情況下,我們需要將字符串轉(zhuǎn)換為日期類型以便進(jìn)行日期計(jì)算和比較。本篇文章將詳細(xì)介紹如何使用不
    的頭像 發(fā)表于 11-17 16:27 ?8950次閱讀

    mysql字符串包含某個(gè)字符串

    MySQL是一種開源的關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng),被廣泛用于構(gòu)建Web應(yīng)用程序和其他大型數(shù)據(jù)驅(qū)動(dòng)的應(yīng)用。在進(jìn)行MySQL數(shù)據(jù)庫(kù)查詢時(shí),經(jīng)常需要使用字符串包含操作,即判斷一個(gè)字符串是否包含另一個(gè)字符串。本文
    的頭像 發(fā)表于 11-16 14:52 ?2982次閱讀

    代碼字符串分割方法

    我們寫代碼的時(shí)候,經(jīng)常會(huì)遇到這樣一個(gè)場(chǎng)景,那就是分割字符串。比如說(shuō)把一個(gè)字符串分成N個(gè),或者說(shuō)按照N個(gè)字符分割。 我們今天就來(lái)看看怎么每隔N個(gè)字符分割
    的頭像 發(fā)表于 09-25 11:42 ?685次閱讀