leetcode-394字符串解码

420 阅读3分钟

给定一个经过编码的字符串,返回它解码后的字符串。

编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。

你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。

此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数k ,例如不会出现像 3a 或 2[4] 的输入。

示例:

s = "3[a]2[bc]", 返回 "aaabcbc".
s = "3[a2[c]]", 返回 "accaccacc".
s = "2[abc]3[cd]ef", 返回 "abcabccdcdcdef".
  • 思路1

分析题意,其实就是将[]内部的字符以前面的数字作为倍数展开,需要注意的是可能存在[]嵌套的情况。和括号匹配有点类似,利用来解决问题。

  1. 遍历字符串s,如果s[i]!=']',入栈
  2. 如果s[i]==']',此时需要我们依次出栈,找到[]内部需要展开的字符以及展开字符的倍数,将所得字符展开并且入栈
示例:3[a2[c]]
1. 依次入栈                         ---> 3[a2[c
2. 遇到']',出栈至'[',获得需要展开的字符c以及需要展开的倍数2
3. 将字符c展开并入栈                ---> 3[acc
4. 继续遍历,遇到第二个']'
5. 回到第2步,获得需要展开的字符acc以及倍数3
6. acc展开并入栈                    ---> accaccacc
7. 遍历结束
char* decodeString(char * s){
    if(s==NULL) return NULL;
    int top = -1;
    //使用char数组来模拟stack。
    char *stack = (char *)malloc(5000);
    char *tmp = (char *)malloc(2000);

    for(int i = 0; s[i]; i++) {
        if(s[i] != ']') {
            stack[++top] = s[i];
        }else {
            //找到[]内部的字符
            int tmpCount = 0;
            while(stack[top] != '[') {
                tmp[tmpCount++] = stack[top];
                top--;
            }
            //弹出[
            top--;
            //寻找倍数k
            int k = 0;
            int multpy = 1;
            //需要先判断top!=-1否则的话会出现数组越界的情况
            while(top!=-1 && (stack[top] >= '0' && stack[top] <= '9') ) {
                k += (stack[top]-'0')*multpy;
                multpy *= 10;
                top--;
            }
            //根据次数k将[]内部的字符入栈
            while(k--) {
                for(int start = tmpCount-1; start >= 0; start--) {
                    top++;
                    stack[top] = tmp[start];
                }
            }
        }
    }
    stack[++top] = '\0';
    free(tmp);
    return stack;
}
  • 思路2
    其实每一次的展开都是一次重复的过程,可以使用递归来解决此问题
  1. 遇到字符,放入结果res
  2. 遇到数字,计算倍数
  3. 遇到[,对[内部进行递归
  4. 遇到],递归结束,返回res以及标志位
  5. char **e的目的是为了告诉上一层递归函数遍历继续进行的位置。因为[]内部的字符已经计算完毕。
char* decodeString_inner(char * s, char **e) {
    char *res = (char*)malloc(5000);
    int idx = 0;
    char *buff = NULL;
    char *end = NULL;
    int count = 0;
    while(*s != '\0') {
        if(isalpha(*s)) {
            res[idx++] = *s;
        }else if(isdigit(*s)) {
            count = 10 * count + (*s - '0');
        }else if(*s == '[') {
            //对[]内部进行递归
            buff = decodeString_inner(s+1, &end);
            //将结果buff放入res中
            while (count) {
                strcpy(res+idx, buff);
                idx += strlen(buff);
                count--;
            }
            //改变s的位置,因为[]中都已经计算完毕
            s = end;
        }else if(*s == ']') {
            //告诉上一层递归函数下一次遍历需要从]后面的字符开始
            *e = s;
            //因为res是一个很大的字符,因此需要增加结束位置
            res[idx] = '\0';
            return res;
        }
        s++;
    }
    res[idx] = '\0';
    return res;
}

char* decodeString_1(char* s) {
    char *end = "123";
    return decodeString_inner(s, &end);
}