• 271. Encode and Decode Strings



    July-15-2019
    这个题蛮有意思的,有2种做法。
    第一种是encode的时候escape character。
    比如用#来区分不同String,遇到String里有#怎么办,加个别的符号%在前面。
    String里有%怎么办,再加个%%在前面。
    最后的结果就是,#单独出现的话,说明是新的String;遇到%的话可能是%%或者%#代表确实是String的字符。

    public class Codec {
    
        // Encodes a list of strings to a single string.
        public String encode(List<String> strs) {
            StringBuilder sb = new StringBuilder();
            strs.stream().forEach(str -> {
                for (char c : str.toCharArray()) {
                    if (c == '#') {
                        sb.append("%#");
                    } else if (c == '%') {
                        sb.append("%%");
                    } else {
                        sb.append(c);
                    }
                }
                sb.append('#');
            });
            
            return sb.toString();
        }
    
        // Decodes a single string to a list of strings.
        public List<String> decode(String s) {
            List<String> res = new ArrayList<>();
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < s.length(); i ++) {
                char c = s.charAt(i);
                if (c == '%') {
                    sb.append(s.charAt(++ i));
                } else if (c == '#') {
                    res.add(sb.toString());
                    sb = new StringBuilder();
                } else {
                    sb.append(c);
                }
            }
            return res;
        }
    }
    

    另一种做法是加个header作为metadata。length_1#str_1length2#str_2
    [“abc”, “ab”] => “3#abc2#ab”

    **string.indexOf("#", index) -> 从i开始第一个出现"#"的位置。手动操作I也行= =

    public class Codec {
    
        // Encodes a list of strings to a single string.
        public String encode(List<String> strs) {
            StringBuilder sb = new StringBuilder();
            for (String s : strs) {
                sb.append(s.length() + "#" + s);
            }
            return sb.toString();
        }
    
        // Decodes a single string to a list of strings.
        public List<String> decode(String s) {
            List<String> res = new ArrayList<>();
            int lenStart = 0;
            while (lenStart < s.length()) {
                int lenEnd = s.indexOf("#", lenStart);
                int tempStrLen = Integer.valueOf(s.substring(lenStart, lenEnd));
                res.add(s.substring(lenEnd + 1, lenEnd + 1 + tempStrLen));
                lenStart = lenEnd + 1 + tempStrLen;
            }
            return res;
        }
    }
    

    二刷。
    15-Nov-2016

    这个题挺有意思的,感觉工作中很容易遇到这种情况,不过我没找到工作,次奥。。

    一刷用的方法是记录每个string的长度,做一个类似于bitmap的东西。最后encoded string还要记录MAP的每个字符串长度的整数的长度。。大概是这样的
    MAP1#长度1#长度2#长度3#长都4#Str1Str2Str3
    |map1|----------------MAP---------------|-----字符串-----|

    实际上不用这么麻烦。。。。。

    思路还是一样的,要记录每个字符串的长度,还自己选个分隔符。
    encode的时候按顺序就行了。
    {"ab", "b", "abc"} =》
    "2#ab 1#b 3#abc" 实际中间是没有空格的,有空格看着清楚些。

    这样最后decode的时候从左边开始,找分隔符,找到之后passed substring就标记长度的整数,记录下俩,然后按整数在分隔符的基础上读取相应的位,再找下一个分隔符。

    Time: O(k)
    k = num of Strings
    Space: O(n + k)

    public class Codec {
    
        // Encodes a list of strings to a single string.
        public String encode(List<String> strs) {
            StringBuilder sb = new StringBuilder();
            for (String s: strs) {
                sb.append(s.length()).append("#").append(s);
            }
            return sb.toString();
        }
    
        // Decodes a single string to a list of strings.
        public List<String> decode(String s) {
            List<String> res = new ArrayList<>();
            int i = 0;
            while (i < s.length()) {
                int next = s.indexOf('#', i);
                int length = Integer.valueOf(s.substring(i, next));
                res.add(s.substring(next + 1, next + 1 + length));
                i = next + length + 1;
            }
            
            return res;
        }
    }
    

    string1.indexOf(char1, index);记得用。。从index开始第一个出现的char1,或者-1.

    这是一个通用的办法。
    “长度+分隔符+字符串”

    另一个办法是escaping..

    选一个分隔符,比如#,再选一个escaping character,比如/。

    我们在原来数组里的#前面加个escaping character,那原来数组里的#就变成了/#。

    我们在原来数组里的/前面加个escaping character,那原来数组里的/就变成了//。

    有人要问了:如果原来的数组里有//#怎么办?
    我们在原来数组里的/前面加个escaping character,,那原来数组里的//#就变成了////#。

    有人要问了:如果原来的数组里有////#怎么办?
    我们在原来数组里的/前面加个escaping character,,那原来数组里的////#就变成了////////#。

    有人要问了:如果原来的数组里有////////#怎么办?
    我们在原来数组里的/前面加个escaping character,,那原来数组里的////////#就变成了////////////////#。
    有人要问了:如果我变成回忆,最怕我太不争气,顽固地赖在空气霸占你心里,每一寸缝隙

    主要想说的是,decode的时候,遇到/我们直接跳过当前,添加他后面的char,/#的#会被直接写入,而不是当做分隔符。
    原来的/#经过encode变成///#,decode的时候第一个/被跳过,直接添加第二个/,然后又遇到一个/,再跳过,直接添加#.

    Time: O(n)
    Space: O(n)

    2个方法是时间和空间的取舍,第一个快,按字符串添加,但是需要额外空间记录长度;第二个慢,按字符一个一个添加,但是不用记录字符串长度了,额外空间少。

    public class Codec {
    
        // Encodes a list of strings to a single string.
        public String encode(List<String> strs) {
            StringBuilder sb = new StringBuilder();
            
            for (String s: strs) {
                for (int i = 0; i < s.length(); i++) {
                    char c = s.charAt(i);
                    if (c == '#') sb.append("/#");
                    else if (c == '/') sb.append("//");
                    else sb.append(c);
                }
                sb.append('#');
            }
            return sb.toString();
        }
    
        // Decodes a single string to a list of strings.
        public List<String> decode(String s) {
            List<String> res = new ArrayList<>();
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < s.length(); i++) {
                char c = s.charAt(i);
                if (c == '/') {
                    sb.append(s.charAt(++i));
                } else if (c == '#') {
                    res.add(sb.toString());
                    sb = new StringBuilder();
                } else {
                    sb.append(c);
                }
            }
            
            return res;
        }
    }
    
  • 相关阅读:
    IE 11 使用 flexbox 垂直居中 bug
    Electron build 无法下载 winCodeSign 等资源
    Electron 开发环境下总是 crash
    解决 Electron 包下载太慢问题
    Netty--数据通信和心跳检测
    Netty编解码技术和UDP实现
    Netty入门
    Java 网络IO编程(BIO、NIO、AIO)
    java.util.concurrent常用类(CountDownLatch,Semaphore,CyclicBarrier,Future)
    JDK多任务执行框架(Executor框架)
  • 原文地址:https://www.cnblogs.com/reboot329/p/5951367.html
Copyright © 2020-2023  润新知