271. Encode and Decode Strings

最后更新

三刷
13-Jan-2017

escape符做法。

加密的时候以#作为分割,那碰到真的#怎么办,我们用/#表示真正的#,遇到/呢? 用//表示真正的/。。
这里/就是escape character..

看到自己二刷的解释。。真是:


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

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

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

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

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

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

public class Codec {

    // Encodes a list of strings to a single string.
    public String encode(List<String> strs) {
        if (strs.size() == 0) return "";
        StringBuilder sb = new StringBuilder();
        
        for (String s : strs) {
            for (char c : s.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<>();
        if (s.length() == 0) return res;
        
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (c == '/') {
                c = s.charAt(++i);
                sb.append(c);
            } else if (c == '#') {
                res.add(sb.toString());
                sb = new StringBuilder();
            } else {
                sb.append(c);
            }
        }
        
        return res;
    }
}

// Your Codec object will be instantiated and called as such:
// Codec codec = new Codec();
// codec.decode(codec.encode(strs));

二刷。
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;
    }
}

转载于:https://www.cnblogs.com/reboot329/p/5951367.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值