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