880. 索引处的解码字符串

给定一个编码字符串 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”。

提示:

2 <= S.length <= 100
S 只包含小写字母与数字 2 到 9 。
S 以字母开头。
1 <= K <= 10^9
解码后的字符串保证少于 2^63 个字母。

思路:
一开始是想着把字符串展开成一个大的字符串然后求解,后来发现当里面数字很多的时候,会发生内存溢出
因此没有必要展开
如果我们有一个像 appleappleappleappleappleapple 这样的解码字符串和一个像 K=24 这样的索引,那么如果 K=4,答案是相同的。

一般来说,当解码的字符串等于某个长度为 size 的单词重复某些次数(例如 apple 与 size=5 组合重复6次)时,索引 K 的答案与索引 K % size 的答案相同。

我们可以通过逆向工作,跟踪解码字符串的大小来使用这种洞察力。每当解码的字符串等于某些单词 word 重复 d 次时,我们就可以将 k 减少到 K % (Word.Length)。

算法

首先,找出解码字符串的长度。之后,我们将逆向工作,跟踪 size:解析符号 S[0], S[1], …, S[i] 后解码字符串的长度。

如果我们看到一个数字 S [i],则表示在解析 S [0],S [1],…,S [i-1] 之后解码字符串的大小将是 size / Integer(S[i])。 否则,将是 size - 1。

这是错误的思路,把字符串展开成完整的,数字太多时,内存溢出。


class Solution {
public:
	string decodeAtIndex(string S, int K) 
	{
		int count = 0;
		int n = 0;
		string temp = "";
		while (S[count] != '\0')
		{
			if (S[count] - '0' >= 2 && S[count] - '0' <= 9)
			{
				string s1 = S.substr(0, temp.length());
				string s2 = "";
				if (S[count + 1] != '0')
					s2 = S.substr(count + 1, S.length() - count - 1);
				for (int i = 0; i < S[count] - '0'-1; ++i)
					temp += s1;
				count = temp.length() - 1;
				S = temp + s2;
			}
			else
			{
				temp += S[count];
			}
			count++;
		}
		temp = "";
		temp += S[K - 1];
		return temp;
	}
};

正确的解法:

class Solution {
public:
	string decodeAtIndex(string S, int K)
	{
		long size = 0;
		int N = S.size();

		//计算S展开后的长度size
		for (int i = 0; i < N; ++i)
		{
			if (isdigit(S[i]))
				size *= (S[i] - '0');
			else
				size++;
		}

		//倒序遍历,直到K%size==0
		for (int i = N - 1; i >= 0; --i)
		{
			K %= size;
			if (K == 0 && isalpha(S[i]))
				return (string)"" + S[i];

			if (isdigit(S[i]))
				size /= (S[i] - '0');
			else
				size--;
		}
		return "";
	}
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值