一、题目描述
给定一个经过编码的字符串,返回它解码后的字符串。
编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。
你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[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.根据题意和示例2可知,每遇到“["需要进行一次字符解析,且允许嵌套;因此可以使用递归的方式解决。
2.可以使用递归解决的问题,也可以采用栈的方式解决。
三、代码范例1——【算法思路:递归】
#define MAX_SIZE (100000)
char *CoreFunc(char *s, int start, int *end)
{
char *ret = (char *)malloc(sizeof(char) * MAX_SIZE);
// memset(ret, '\0', sizeof(char) * MAX_SIZE);//如果后面不写繁琐的'\0',可以加上此句
int retNum = 0;
int multi = 0;
while (start < strlen(s)) {
if (s[start] == '[') {
char *temp = CoreFunc(s, start + 1, end);
int tempLen = strlen(temp);
for (int i = 0; i < multi; i++) {
strncpy(&ret[retNum], temp, tempLen);// ret没有结束符,不能使用strcpy
retNum += tempLen;
}
multi = 0;
free(temp);
start = *end;
} else if (s[start] >= '0' && s[start] <= '9') {
multi = multi * 10 + (s[start] - '0');
start += 1;
} else if (s[start] == ']') {
*end = start + 1;
ret[retNum] = '\0';//递归时返回置结束符
return ret;
} else {
ret[retNum++] = s[start];
start += 1;
}
}
ret[retNum] = '\0';//最外一层通过while体外返回
*end = start;
return ret;
}
char *decodeString(char *s)
{
if (NULL == s) {
return NULL;
}
int end = 0;
return CoreFunc(s, 0, &end);
}
三、代码范例2——【算法思路:单栈】
#define MAX_LEN 10000
typedef struct tagStack {
char s[MAX_LEN];
int cnt;
int dup;
} Stack;
char *decodeString(char *s)
{
int slen = strlen(s);
int depth = slen / 2 + 1;
Stack *stk = (Stack *)calloc(depth, sizeof(Stack));
// 栈顶为ssize而非ssize-1
int ssize = 0;
int dup = 0;
for (int i = 0; i < slen; i++) {
if (s[i] >= '0' && s[i] <= '9') {
dup = dup * 10 + s[i] - '0';
} else if (s[i] == '[') {
ssize++;
stk[ssize].dup = dup;
dup = 0;
} else if (s[i] == ']') {
// 将当前站内元素,重复dup次赋值给上一级
for (int j = 0; j < stk[ssize].dup; j++) {
for (int k = 0; k < stk[ssize].cnt; k++) {
stk[ssize - 1].s[stk[ssize - 1].cnt++] = stk[ssize].s[k];
}
}
stk[ssize].cnt = 0;
stk[ssize].dup = 0;
ssize--;
} else {
stk[ssize].s[stk[ssize].cnt++] = s[i];
}
}
return stk[ssize].s;
}
三、代码范例3——【算法思路:双栈】
#define MAX_SIZE 10000
void reverse(char *s)
{
for (int i = 0, j = strlen(s) - 1; i < j; i++, j--) {
char tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}
}
char *decodeString(char *s)
{
char letter[MAX_SIZE] = "";
int nums[MAX_SIZE] = { 0 };
int ltop = -1, ntop = -1;
int tmp = 0;
for (int i = 0; i < strlen(s); i++) {
if (s[i] == '[') {
nums[++ntop] = tmp;
letter[++ltop] = '['; // 将'['入栈
tmp = 0; // tmp归0
} else if (s[i] == ']') {
// 保存[XXX]之间的字符
char str[1000] = "";
int k = 0;
while (letter[ltop] != '[') {
str[k++] = letter[ltop--];
}
ltop--; // 将’[’出栈
reverse(str);
// 将字符进堆栈
int times = nums[ntop--]; // 倍数
for (int i = 0; i < times; i++) {
for (int j = 0; j < k; j++) {
letter[++ltop] = str[j];
}
}
} else if (s[i] >= '0' && s[i] <= '9') {
tmp = tmp * 10 + (s[i] - '0');
} else {
letter[++ltop] = s[i];
}
}
char *ans = malloc(sizeof(char) * MAX_SIZE);
ans[0] = '\0';
strcat(ans, letter); // strcat要求src和dst都必须有'\0',否则不知道copy多少和目的端起始位置
return ans;
}