迭代压缩字符串

迭代压缩字符串

对于一个压缩字符串,设计一个数据结构,它支持如下两种操作: next 和 hasNext。

给定的压缩字符串格式为:每个字母后面紧跟一个正整数,这个整数表示该字母在解压后的字符串里连续出现的次数。

next() - 如果压缩字符串仍然有字母未被解压,则返回下一个字母,否则返回一个空格。
hasNext() - 判断是否还有字母仍然没被解压。

注意:

请记得将你的类在 StringIterator 中 初始化 ,因为静态变量或类变量在多组测试数据中不会被自动清空。更多细节请访问 这里 。

示例:

StringIterator iterator = new StringIterator(“L1e2t1C1o1d1e1”);

iterator.next(); // 返回 ‘L’
iterator.next(); // 返回 ‘e’
iterator.next(); // 返回 ‘e’
iterator.next(); // 返回 ‘t’
iterator.next(); // 返回 ‘C’
iterator.next(); // 返回 ‘o’
iterator.next(); // 返回 ‘d’
iterator.hasNext(); // 返回 true
iterator.next(); // 返回 ‘e’
iterator.hasNext(); // 返回 false
iterator.next(); // 返回 ’ ’

当字符串重复次数很大时下面解法超时,如当字符串为a1212323234b2354235342

package com.company;

public class StringIterator {
    private String str;

    private int index = 0;
    private char []deChars = null;

    public StringIterator(String compressedString) {
        str = compressedString;

        deChars =  decompressString().toCharArray();
    }

    public char next() {
        if(hasNext()){
            return deChars[index++];
        }
        return ' ';
    }

    public boolean hasNext() {
        return index < deChars.length;
    }

    public String decompressString(){
        /**
         *快慢指针法解压字符串
         * i指向字母,j指向下一个字母,i,j之间的数字为重复个数cnt
         * 将i位置的字母重复cnt次,组成新的解压的字符串
         * 时间O(n^2),空间O(n)
         */
        StringBuffer sb = new StringBuffer();

        int i = 0, j = i+1;
        while(j < str.length()){
            if(j+1 == str.length() || (str.charAt(j) >= 'a' && str.charAt(j) <= 'z')
            || (str.charAt(j) >= 'A' && str.charAt(j) <= 'Z')){
                //当j走到最后最后一个元素时,要将其值变为字符串长度,以取子串时能取到最后
                j = j+1 == str.length() ? str.length(): j;
                String subNumStr = str.substring(i+1, j);

                int cnt = Integer.parseInt(subNumStr);
                while (cnt > 0){
                    sb.append(str.charAt(i));
                    cnt--;
                }

                i = j;
            }
            j++;
        }
        System.out.println(sb.toString());
        return sb.toString();

    }

    public static void main(String []args){
        /**
         * ["StringIterator","next","next","next","next","next","next","hasNext","next","hasNext"]
         * [["L2e2t2C2o2d2e23"],[],[],[],[],[],[],[],[],[]]
         */
        StringIterator obj = new StringIterator("a1212323234b2354235342");

        char param_1 = obj.next();
        boolean param_2 = obj.hasNext();
        System.out.println(param_1 + " " + String.valueOf(param_2));

        char param_11 = obj.next();
        boolean param_21 = obj.hasNext();
        System.out.println(param_11 + " " + String.valueOf(param_21));

        char param_12 = obj.next();
        boolean param_22 = obj.hasNext();
        System.out.println(param_12 + " " + String.valueOf(param_22));
    }
}

在这里插入图片描述

下面的方法不需要先构建字符串,是需要的时候解压字符串

public class StringIterator {
    /**
     * 1.定义函数decompose,每次都能找到下一个需要打印的字符curChar和其数量curCnt,记录之,同时
     * 如果找到就返回真,找不到返回假
     * 2.判断是否有下一个元素的方法:如果curCnt>0,则代表当前的字符还没有打印完,当然有下一个字符,返回真
     * 如果curCnt<=0,则说明当前字符已经打印完成,那就要看能不能找到下一个需要打印的字符了,调用decompose
     * 就会知道有没有下一个需要打印的字符
     *3.时间主要在decompose上,为O(n),空间O(1)
     */
    private String str;

    private int i = 0;
    private int j = 1;

    private char curChar;
    private int curCnt = 0;

    public StringIterator(String compressedString) {
        str = compressedString;
    }

    public char next() {
        if(hasNext()){
            curCnt--;
            return curChar;
        }
        return ' ';
    }

    public boolean hasNext() {
        if (curCnt > 0){
            return true;
        }else{
            return decompose();
        }

    }

    public boolean decompose(){
        if(j >= str.length()){
            //表示是否还能够继续处理字符串
            return false;
        }
        //j一直走到不为数字的位置
        while(j < str.length() && str.charAt(j) >= '0' && str.charAt(j) <= '9'){
            j++;
        }
        //j可能走到末尾,截取子串时需要下面处理
        j = j+1 >= str.length() ? str.length(): j;
        String subNumStr = str.substring(i+1, j);
        int cnt = Integer.parseInt(subNumStr);
        //记录当前的字符和数量
        curChar = str.charAt(i);
        curCnt = cnt;

        //下一次调用函数的时候i和j的位置
        i = j;
        j++;

        //表示是否处理了字符串,有结果出来
        return true;
    }
    

    public static void main(String []args){

        StringIterator obj = new StringIterator("L2342e2");

        boolean param_2= true;
        while (param_2){
            char param_1 = obj.next();
            param_2 = obj.hasNext();
            System.out.println(param_1 + " " + String.valueOf(param_2));
        }

    }
}

在这里插入图片描述

上面的代码decompose部分太过于繁琐,简化处理后为

package com.company;

public class StringIterator {
    /**
     * 1.定义函数decompose,每次都能找到下一个需要打印的字符curChar和其数量curCnt,记录之,同时
     * 如果找到就返回真,找不到返回假
     * 2.判断是否有下一个元素的方法:如果curCnt>0,则代表当前的字符还没有打印完,当然有下一个字符,返回真
     * 如果curCnt<=0,则说明当前字符已经打印完成,那就要看能不能找到下一个需要打印的字符了,调用decompose
     * 就会知道有没有下一个需要打印的字符
     *3.时间为O(1),空间O(1)
     */
    private String str;

    private int i = 0;

    private char curChar;
    private int curCnt = 0;

    public StringIterator(String compressedString) {
        str = compressedString;
    }

    public char next() {
        if(hasNext()){
            curCnt--;
            return curChar;
        }
        return ' ';
    }

    public boolean hasNext() {

        return curCnt > 0 || decompose();
    }

    public boolean decompose(){
        if(i >= str.length()){
            return false;
        }
        curChar = str.charAt(i++);
        curCnt = 0;

        while (i < str.length() && Character.isDigit(str.charAt(i))){
            curCnt += curCnt * 10 + str.charAt(i++) - '0';
        }

        return true;
    }


    public static void main(String []args){

        StringIterator obj = new StringIterator("L2342e2");

        boolean param_2= true;
        while (param_2){
            char param_1 = obj.next();
            param_2 = obj.hasNext();
            System.out.println(param_1 + " " + String.valueOf(param_2));
        }

    }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值