可以嵌套的数据集的字符串压缩和解压缩

时间:2017-09-21 15:40:15

标签: java algorithm data-structures

我的输入是格式编号为[string]的压缩字符串,解压缩的输出格式应为写入次数的字符串。例如:

3[abc]4[ab]c = abcabcabcababababc

2[3[a]b] = aaabaaab.

我在Java中的蛮力方法:

public class CompresnDecompresn {

    public static void main(String[] args) {

        String s="3[abc]4[ab]c";
        for (int i = 0; i<s.length(); i++)  {
            if(s.charAt(i)==']') {
                int j=i-1;
                while(true)  {
                    if(s.charAt(j)=='[') {
                        break;
                    }
                    j--;
                }
                int k=j-1;
                while(true) {
                    if(k<0) {
                        break;
                    }
                    int m=(int)s.charAt(k);
                    if(m<48 || m>57) {
                        break;
                    }
                    k--;
                }
                k++;
                int freq=Integer.parseInt(s.substring(k, j));
                String snippet=s.substring(j+1,i);
                String temp="";

                for (int l = 0; l < freq; l++) {
                    temp+=snippet;
                }
                s=s.substring(0,k)+temp+s.substring(i+1);
            }
        }        
        System.out.println(s);                
    }    
}

我能以更低的成本获得更好的方法吗?

5 个答案:

答案 0 :(得分:2)

由于您使用Java,因此请随意使用Java提供的功能,以使解决方案更具可读性和直接性。这里使用正则表达式以及使用StringBuilder连接字符串。

考虑输入String string ="3[abc]4[ab]c";就个人而言,我会选择这样的事情:

首先定义持有数字字母对的Couple类。

private static class Couple {

    public int x;
    public String y;

    public Couple(int x, String y) {
        this.x = x;
        this.y = y;
    }
}

我们走了:

// Regex to extract the number before '[' and the content inside of '[]'
Pattern p = Pattern.compile("(\\d+)\\[(.*?)\\]");
Matcher m = p.matcher(string);

// Coupling the number and the letters
List<Couple> couples = new ArrayList<>();
while (m.find()) {
    couples.add(new Couple(Integer.parseInt(m.group(1)), m.group(2)));
}

// Concatenating String together using the for-cycle
String rest = string.substring(string.lastIndexOf("]")+1, string.length());
StringBuilder sb = new StringBuilder();

for (Couple c: couples) {
    for (int i=0; i<c.x; i++) {
        sb.append(c.y);
    }
}

// Enjoying the result
sb.append(rest);
System.out.println(sb.toString());

请记住,对于您的问题,这只是一个愚蠢的天真解决方案,以防始终存在格式为

的输入字符串
number[string]number[string]number[string]rest // more of number[string] pairs

你必须广泛思考是否有地方需要注意失败的代码。如果没有rest怎么办?如果用户的输入格式不同(永远不要信任用户的输入)怎么办 - 所以不值得对Regex进行验证吗?你必须向自己提出问题,然后开始如果发生了什么

无论如何,您可以从我的实施开始,然后根据需要继续。

答案 1 :(得分:0)

我们实际上希望在return (T)(object) new Series<float>(); 中找到字符串并重复[]之前指定的n次。但问题是这些字符串是嵌套的。 因此,当我们调用在[]中读取字符串的函数时,它应该在遇到新的[]时再次调用自身。因此,这会导致递归解决方案,我们只在输入字符串中循环一次。

[]

答案 2 :(得分:0)

通过递归解决问题将是方便的解决方案。跟踪嵌套[]的一种更简单方法是,每次遇到open时递增[变量,并在遇到]时递减它,并递归调用deCompress()当你遇到]时。

public String deCompress(int times, String ip) {
String op = "";
int open = 0;
char a;
int start = 0;
int t=0;
String expand = "";
for (int i = 0; i < ip.length(); i++) {
  a = ip.charAt(i);
  if (Character.isDigit(a) && open == 0) {
    //Calculates times
    t = t * 10 + Integer.parseInt(""+a);
    //We want to expand and append to the output
    if (expand != "") {
      op += expand;
      expand = "";
    }
  }
  else if(a == '[') {
    //start index for substring : Recursive solution
    if(open == 0) {
      start = i + 1;
    }
    open++;
    continue;
  }
  else if(a == ']') {
    //Recursive solution for nested compression
    open--;
    if(open == 0) {
      expand = deCompress(t, ip.substring(start, i));
      t = 0;
    }
    continue;
  }
  else {
    if (open == 0) {
      expand += a;
    }
  }
}
//Append the expanded string to the output for strings with 0 times
if(times == 0) {
  op += expand;
}
//Expand string x times
for (int j = 1; j<=times; j++) {
  op += expand;
}
return op;

}

只需调用此函数 -

deCompress(0, "3[abc]4[ab]c2[3[a]b]")

答案 3 :(得分:0)

我已经使用堆栈来解决问题。

from collections import deque
st=input("Enter a compressed string: ")
myStack=deque()
numstring=""
alphastring=""
for i in range(len(st)):
     ch=st[i]
     print(myStack)
     if ch.isdigit():
          numstring+=ch
          if alphastring!="":
               myStack.append(alphastring)
               alphastring=""
     elif ch=='[':
          myStack.append(numstring)
          numstring=""
     elif ch.isalpha():
          alphastring+=ch
     elif ch==']':
          top=myStack.pop()
          if top.isnumeric():
               check=""
               m=int(top)
               word=alphastring*m
               if len(myStack)>0:
                    check=myStack.pop()
                    if(check.isalpha()):
                         word=check+word
                    else:
                         myStack.append(check)
               myStack.append(word)
               alphastring=""

          else:
               m=int(myStack.pop())
               myStack.append((top+alphastring)*m)
               alphastring=""
solution=alphastring
while(len(myStack)>0):
     solution=myStack.pop()+solution
print("Decompressed : ",solution)

答案 4 :(得分:0)

@Test()
public void googleProblemSolve() {
    String mainString = "3[abc]4[ab]c10[a]9[x]15[d]";
    // Split the string using end bracket
    String sep[] = mainString.split("\\]");

    for (int i = 0; i < sep.length; i++) {
        // remove start bracket from the each index to get iteration count
        String[] subSep = sep[i].split("\\[");
        
        /* before part of the split string would be iteration count and second part
         would be the actual string*/
        repeatWords(subSep[0], subSep[1]);
    }

}

private void repeatWords(String iteration, String str) {
    int ite = 0;
    String newStr = str;

    // iteration value can throw exception if the string is like i.e. c10
    try {
        ite = Integer.parseInt(iteration);
    } catch (NumberFormatException e) {
        /*
         * consider the first char in the string would be the alphabet with no
         * repeatation
         */
        newStr = Character.toString(iteration.charAt(0));

        // check the length of the string;
        // if its three means iteration count is in 2 digit
        if (iteration.length() == 3) {
            ite = Character.getNumericValue(iteration.charAt(1) + iteration.charAt(2));
        } else {
            ite = Integer.parseInt(String.valueOf(iteration.charAt(1)));
        }
    }

    for (int i = 0; i < ite - 1; i++) {
        newStr = newStr + str;
    }
    System.out.print(newStr);
}

我想这可能是这个问题的最佳解决方案。请分享您的想法。