leetcode394。文字列のデコード

エンコードされた文字列を指定すると、デコードされた文字列を返します。

エンコード規則は次のとおりですk[encoded_string]。これは、角かっこがencoded_string正確にk何回繰り返されるかを意味します。k正の整数であることが保証されていることに注意してください。

入力文字列は常に有効であり、入力文字列には余分なスペースがなく、入力角括弧は常に整形式であると想定できます。

また、元のデータには数字が含まれていないと考えることができます。すべての数字は繰り返しの数を表すだけです。kたとえば、3aやのような入力はありません2[4]

例1:
 入力:s = "3 [a] 2 [bc]"
 出力: "aaabcbc"

例2:
 入力:s = "3 [a2 [c]]"
 出力: "accaccacc"

アイデア:
入力文字列には角かっこがネストされている場合があります。このとき、最初に内側の角かっこで文字列をデコードし、次に外側の角かっこで文字列をデコードします。つまり、左から文字列をトラバースするときに移動します。そうです、[最初にトラバースされた内部文字列は後でデコードされます。これは、ファーストイン、ラストアウトスタックの特性に沿っているため、スタックを使用してこの問題を解決できます。

入力文字列のトラバースは次のように実行されます。

  • トラバーサルは数値であり、最初に完全な数値文字列を抽出してから、スタックをプッシュします。
  • トラバーサルは文字または'['であり、スタックに直接プッシュされます。
  • トラバーサルは、']'最初にコピーする文字列を取得してからコピーすることです。コピーした文字列をスタックにプッシュバックするのが最適です。

トラバースした場合']'の具体的な操作手順は次のとおりです。

  1. 最初にスタックをポップし、ポップされた文字列をベクターに保存し、「[」がポップされるまでスタックのポップを停止し、「[」がベクターに保存されないようにします。
  2. 次に、ポップの順序がスタックの順序と反対であるため、ベクトルの内容を反転します。
  3. 次に、コピーするいくつかの文字列をスプライスして、コピーする最終的な文字列を取得します。
  4. この時点でスタックの一番上にある数値文字列をポップし、整数numに変換します。
  5. コピーする文字列をnum回コピーし、最後にコピーした文字列を取得します。
  6. コピーした文字列をスタックにプッシュします。

最後に、入力文字列がトラバースされると、スタック内の文字列をスプライスすることによって、最終的にデコードされた文字列が取得されます。

アニメーションデモ:
ここに画像の説明を挿入
コードは次のとおりです。

class Solution {
    
    
public:
	//从字符串s的pos位置开始,提取数字字符串
	string GetNum(string& s, size_t& pos)
	{
    
    
		string num;
		while (s[pos] != '[')
		{
    
    
			num += s[pos];
			pos++;
		}
		return num;
	}
	//将vector当中的字符串拼接后进行返回
	string GetString(vector<string>& st)
	{
    
    
		string s;
		for (auto e : st)
		{
    
    
			s += e;
		}
		return s;
	}
	string decodeString(string s) {
    
    
		vector<string> st; //数组模拟栈
		size_t pos = 0; //用于遍历字符串s
		while (pos < s.size())
		{
    
    
			//1、遍历到的是数字,先将完整的数字字符串提取出来,然后进行压栈
			if (isdigit(s[pos]))
			{
    
    
				string num = GetNum(s, pos);
				st.push_back(num);
			}
			//2、遍历到的是字母或'[',直接将其进行压栈
			else if (isalpha(s[pos]) || s[pos] == '[')
			{
    
    
				st.push_back(string(1, s[pos]));
				pos++;
			}
			//3、遍历到的是']',先获取到待复制的字符串,再将其进行复制,最好将复制后的字符串重新进行压栈
			else
			{
    
    
				vector<string> sub; //待复制的若干字符串
				//a、先进行弹栈,将弹出的字符串保存到vector当中,直到'['被弹出时停止弹栈,'['不保存到vector中
				while (st.back() != "[")
				{
    
    
					sub.push_back(st.back());
					st.pop_back();
				}
				st.pop_back();

				//b、再将vector当中的内容进行逆置,因为出栈的顺序与入栈顺序相反
				reverse(sub.begin(), sub.end());

				//c、然后将待复制的若干字符串进行拼接,得到最终待复制的字符串
				string all = GetString(sub);

				//d、弹出此时栈顶的数字字符串,并将其转换成整数num
				int num = stoi(st.back());
				st.pop_back();

				//d、将待复制的字符串复制num次,最终得到复制后的字符串
				string str; //复制后的字符串
				while (num--)
				{
    
    
					str += all;
				}

				//e、将复制后的字符串进行压栈
				st.push_back(str);

				pos++;
			}
		}
		return GetString(st); //将栈当中的字符串拼接后进行返回
	}
};

コードの説明:

  • コードは実際のスタックを使用しませんが、スタックの最下部から最上位へのトラバーサルを容易にするために、ベクトルを使用してスタックのプッシュとポップをシミュレートします。(これは重要なポイントです)
  • GetNum関数のパラメーターposは、文字列をトラバースするために常に同じpos変数を使用していることを確認するために、参照によって渡される必要があります。

おすすめ

転載: blog.csdn.net/chenlong_cxy/article/details/123239282