实现迷你解析器把字符串解析成NestInteger类 Mini Parser

问题:

Given a nested list of integers represented as a string, implement a parser to deserialize it.

Each element is either an integer, or a list -- whose elements may also be integers or other lists.

Note: You may assume that the string is well-formed:

  • String is non-empty.
  • String does not contain white spaces.
  • String contains only digits 0-9[- ,].

Example 1:

Given s = "324",
You should return a NestedInteger object which contains a single integer 324.

Example 2:

Given s = "[123,[456,[789]]]",
Return a NestedInteger object containing a nested list with 2 elements:
1. An integer containing value 123.
2. A nested list containing two elements:
    i.  An integer containing value 456.
    ii. A nested list with one element:
         a. An integer containing value 789.

解决:

【题意】这道题让我们实现一个迷你解析器用来把一个字符串解析成NestInteger类。

对输入的每个字符进行判断 
数字: 用l保存开始 用i保存数字最后一位的下一位 用substring进行裁剪 
字符‘[’ :遇到 [ 时将上一级的NestedInteger保存入栈 进行下一步操作 
字符’]’:判断是否需要将数字加入当前NestedInteger,然后将上一级NestedInteger弹出 将这一级的NestedInteger加入到上一级的NestedInteger中去 
字符’,’判断是否要将数字加入当前NestedInteger

① 递归方法解决。首先判断s是否为空,为空直接返回,不为空的话看首字符是否为'[',不是的话说明s为一个整数,我们直接返回结果。如果首字符是'[',且s长度小于等于2,说明没有内容,直接返回结果。反之如果s长度大于2,我们从i=1开始遍历,我们需要一个变量start来记录某一层的起始位置,用count来记录跟起始位置是否为同一深度,count=0表示同一深度,由于中间每段都是由逗号隔开,所以当我们判断当count为0,且当前字符是逗号或者已经到字符串末尾了,我们把start到当前位置之间的字符串取出来递归调用函数,把返回结果加入res中,然后start更新为i+1。如果遇到'[',计数器count自增1,若遇到']',计数器count自减1。

class Solution { //17ms
    public NestedInteger deserialize(String s) {
        NestedInteger res = new NestedInteger();
        if (s == null || s.length() == 0) return res;
        if (s.charAt(0) != '[') {
            res.setInteger(Integer.parseInt(s));
        } else if (s.length() > 2) {
            int start = 1, count = 0;
            for (int i = 1; i < s.length(); i++) {
                char c = s.charAt(i);
                if (count == 0 && (c == ',' || i == s.length() - 1)) {
                    res.add(deserialize(s.substring(start, i)));
                    start = i + 1;
                }
                else if (c == '[') count++;
                else if (c == ']') count--;
            }
        }
        return res;
    }
}

② 非递归方法,用栈维护一个包含关系。

/**
* // This is the interface that allows for creating nested lists.
* // You should not implement it, or speculate about its implementation
* public interface NestedInteger {
*     // Constructor initializes an empty nested list.
*     public NestedInteger();
*
*     // Constructor initializes a single integer.
*     public NestedInteger(int value);
*
*     // @return true if this NestedInteger holds a single integer, rather than a nested list.
*     public boolean isInteger();
*
*     // @return the single integer that this NestedInteger holds, if it holds a single integer
*     // Return null if this NestedInteger holds a nested list
*     public Integer getInteger();
*
*     // Set this NestedInteger to hold a single integer.
*     public void setInteger(int value);
*
*     // Set this NestedInteger to hold a nested list and adds a nested integer to it.
*     public void add(NestedInteger ni);
*
*     // @return the nested list that this NestedInteger holds, if it holds a nested list
*     // Return null if this NestedInteger holds a single integer
*     public List<NestedInteger> getList();
* }
*/

class Solution{ //23ms
    public NestedInteger deserialize(String s) {
        Stack<NestedInteger> stack = new Stack<NestedInteger>();
        String tokenNum = "";
        for (char c : s.toCharArray()) {
            switch (c) {
                case '['://[代表一个list
                    stack.push(new NestedInteger());
                    break;
                case ']'://list结尾
                    if (!tokenNum.equals(""))//前面token为数字 
                        stack.peek().add(new NestedInteger(Integer.parseInt(tokenNum)));//将数字加入到本层list中
                    NestedInteger ni = stack.pop();//本层list结束
                    tokenNum = "";
                    if (!stack.isEmpty()) {//栈内有更高层次的list
                        stack.peek().add(ni);
                    } else {//栈为空,遍历到字符串结尾
                        return ni;
                    }
                    break;
                case ',':
                    if (!tokenNum.equals("")) //将数字加入到本层list中
                        stack.peek().add(new NestedInteger(Integer.parseInt(tokenNum)));
                    tokenNum = "";
                    break;
                default:
                    tokenNum += c;
            }
        }
        if (!tokenNum.equals(""))//特殊case: 如果字符串只包含数字的情况
            return new NestedInteger(Integer.parseInt(tokenNum));
        return null;
    }
}

③ 在discuss中看到的,使用数组实现栈。。。

class Solution {
    public NestedInteger deserialize(String s) {
        NestedInteger parent = new NestedInteger();
        deserialize(s.toCharArray(), 0, parent);
        return parent.getList().get(0);
    }
    private int deserialize(char[] schar, int i, NestedInteger parent) {
        char c = schar[i++];
        NestedInteger nestedInteger;
        if (c == '[') {
            nestedInteger = new NestedInteger();
            if(schar[i] == ']') {
                i++;
            } else {
                do {
                    i = deserialize(schar, i, nestedInteger);
                } while(schar[i++] != ']');
            }
        } else {
            boolean isNeg = false;
            if (c == '-') {
                isNeg = true;
                c = schar[i++];
            }
            int num = c - '0';
            for (; i < schar.length && (c = schar[i]) >= '0' && c <= '9'; i++) {
                num = num * 10 + c - '0';
            }
            nestedInteger = new NestedInteger(isNeg ? -num : num);
        }
        parent.add(nestedInteger);
        return i;
    }
}

【注】NestedInteger类的简单实现。

class NestedInteger {
    private List<NestedInteger> list;
    private Integer integer;
    public NestedInteger(List<NestedInteger> list){
        this.list = list;
    }
    public void add(NestedInteger nestedInteger) {
        if(this.list != null){
            this.list.add(nestedInteger);
        } else {
            this.list = new ArrayList();
            this.list.add(nestedInteger);
        }
    }
    public void setInteger(int num) {
        this.integer = num;
    }
    public NestedInteger(Integer integer){
        this.integer = integer;
    }
    public NestedInteger() {
        this.list = new ArrayList();
    }
    public boolean isInteger() {
        return integer != null;
    }
    public Integer getInteger() {
        return integer;
    }
    public List<NestedInteger> getList() {
        return list;
    }
    public String printNi(NestedInteger thisNi, StringBuilder sb){
        if(thisNi.isInteger()) {
            sb.append(thisNi.integer);
            sb.append(",");
        }
        sb.append("[");
        for(NestedInteger ni : thisNi.list){
            if(ni.isInteger()) {
                sb.append(ni.integer);
                sb.append(",");
            }
            else {
                printNi(ni, sb);
            }
        }
        sb.append("]");
        return sb.toString();
    }
}

转载于:https://my.oschina.net/liyurong/blog/1596784

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值