给定一个编码字符串 S
。为了找出解码字符串并将其写入磁带,从编码字符串中每次读取一个字符
,并采取以下步骤:
- 如果所读的字符是字母,则将该字母写在磁带上。
- 如果所读的字符是数字(例如
d
),则整个当前磁带总共会被重复写d-1
次。
现在,对于给定的编码字符串 S
和索引 K
,查找并返回解码字符串中的第 K
个字母。
示例1:
输入:S = "leet2code3", K = 10
输出:"o"
解释:
解码后的字符串为 "leetleetcodeleetleetcodeleetleetcode"。
字符串中的第 10 个字母是 "o"。
示例2:
输入:S = "ha22", K = 5
输出:"h"
解释:
解码后的字符串为 "hahahaha"。第 5 个字母是 "h"。
示例3:
输入:S = "a2345678999999999999999", K = 1
输出:"a"
解释:
解码后的字符串为 "a" 重复 8301530446056247680 次。第 1 个字母是 "a"。
*************************************************************************************************************************************************
根据题目要求,基础字符串S按照规则相应的进行膨胀,最简单的思路就是求出膨胀后的新字符串直接输出第K(K是从1计算)个字符;这样暴力枚举的方法就是字符串超出内存限制。
暴力枚举的方法是膨胀字符串,再根据所以求得答案,很明显,我们要反过来做;
原理是:S中的每一个下标pos_s对应一个index和K值
-
按照规则膨胀后字符串S1长度(index)应为index>=K;
-
记录下此时运行到的字符串S下标为止pos_S;
-
按照题目给出的规则,此时运行的规则为:
-
如果S[pos_S]是数字,S1的长度index应回退到增加之前的值,index/=(S[pos_S]-'0'),这样相应K值也应按照S1之前的长度进行回退,K%=index;
-
如果S[pos_S]是字母,S1的长度index减少一;
-
循环4,5,直到K是index的倍数,输出此时的S[pos_S]即可
#include <iostream>
#include <string>
#include <map>
using namespace std;
class Solution {
public:
string decodeAtIndex(string S, int K)
{
long index = 0, pos_S = 0;
for (int i = 0; i < S.length(); i++)
{
if (!isdigit(S[i]))
index++;
else
index = index * (S[i] - '0');
if (index >= K)
{
pos_S = i;
break;
}
}
while (pos_S>=0)
{
if (isdigit(S[pos_S]))
{
index = index / (S[pos_S] - '0');
K = K % index;
}
else if (K % (index) == 0)
{
return { S[pos_S] };
}
else
index--;
pos_S--;
}
}
};
int main()
{
int k = 10;
string s = "leet2code3";
Solution s1;
cout << s1.decodeAtIndex(s, k);
return 0;
}