序列化与压缩
Bencode 格式 “长度 + 分隔符 + 字符串”, 和 OS 里的 metadata header 是一个思路,在最开始告诉你 data 地址 / 长度 / offset
Escape 符的定义是:"An escape character is a character which invokes an alternative interpretation on subsequent characters in a character sequence."
这题挺好玩的,既实用又有意思,做了一番调查之后有两种方法都可以写。
这题考察的就是在 serialization 中如何解决各种歧义,还有 corner case 是否考虑的足够周全。
当发现题目本身重点考察 corner case 的时候,一定记得先列出需要解决的问题,把各种 corner case 先列出来再动手。
输入字符在 256 个 ASC II 码的集合中,所用的 encode 字符也是同一个集合。所以不能引入新的特殊符号去解决问题。
用什么字符做分隔符,表示 string 的间隔?
如果原字符中有分隔符,如何区分?
如何正确的 encode 空字符串,还有多个空字符串?
举个例子,我如果用 '#' 代表字符分隔符,'#' 代表原字符串中的 '#' 的话,几个必须要考虑的 test case 是:
["\"]
["#"]
["\#"]
[""]
["", ""]
先说一下我几次不成功的尝试。。下面的代码不能 AC,只能过 305 / 316 个 test case.
基本 encode 思路是让每个 encoded string 不以 '#' 结尾,落单的 '#' 代表空字符串。
然后 decode 时依次读取,看到字符先加进去,如果发现后面的是 '#' 而前一个是 '\' 的话,抹掉一位。
不过依然解决的不完美,因为下面这个 test case 里
Input: ["" ""]
Output: [""]
Expected: ["",""]
中间的过渡 string 是 "#"。
这个问题在 StackOverflow 上有个帖子讲的不错,思路和我原来的代码也很接近。
BitTorrent 有一个P2P跨平台的序列化规范,简单易懂,叫 Bencode, 简单讲就是 “长度 + 分隔符 + 字符串” 的 encoding.
于是有了这段参考 LeetCode 论坛之后的代码。 其实空间时间上不算特别经济,但是胜在简洁。原 string 中间如果有 delimiter 也不要紧,因为可以根据 length 直接跳过,再寻找 delimiter 的时候一定是有效字符。
思想上讲和 OS 的 file system 是非常像的,在实际 data 最前面的 header 里会存 metadata,告诉你下一段数据的内存地址或者offset。
继续参考了一下论坛的各种解法之后,不利用length信息这题也可以做,只是需要对“escape符”有更好的理解才行。
Escape 符的正确定义是:看到了就跳过,但是 escape 符后面的一定是有效字符。
于是一个落单的 '#' 代表单词 delimiter ;
原字符串的 '#' 变成了 '/ + #';这样保证可以加进去但是又不会作为 '#' 单独被判断;
原字符串的 '/' 就变成了 '//',实际意义是 "escape 符 + 有效字符"。
这题本身非常简单,但是写 sample test case 的人有点智障。。。得看着挂了的 test case 一点一点猜才能知道这题到底是想干啥。
这题的意思是,我们要看的是一个 key 到底是否有效; 给你一个 word,如果字典里面完全没有一样的 abbreviation -> true; 如果有一样的 abbreviation 但是全和你的 word 是一样的单词,也返回 true;其他的都是 false;
典型的搜索问题,对于 "word" ,该词的搜索图和状态空间如图所示:

第一遍 AC 的代码~
错误1:不能盲目用 indexOf(len) 去找下一个起点,因为 len 作为一个数字是可以重复的。
错误2:用 lastIndexOf 也不行,因为数字不都是一位数,有肯能会出现重复数字的两位数。
因此, 最稳的做法是,pos 一定新 string 的起点,然后加上数字 string 的长度,再加一。
参考了论坛之后,觉得这个做法也特别巧妙,图像化的话,和我刚才画的搜索图不一样,而是从原始 String 出发,对于每个位置进行检查;每个位置都有 "加字母" 或者 "不加,并入数字" 两种选择,和 remove parentheses 与 add operators 的思路非常的像,时间复杂度也一目了然,O(2^n).
这种在 String 上,相对于每个字符考虑多种可能的 DFS + backtracking,简单强大,非常值得总结一个~
(Google) 字符串嵌套压缩 / 解压缩
变种1:
http://www.1point3acres.com/bbs/thread-189365-1-1.html
上来大概问了5分钟background然后直接上题,一个string decompression的题。。不知道是不是原题反正没见过。。题目如下.
2[abc]3[a]c => abcabcabcaaac; 2[ab3[d]]2[cc] => abdddabdddcc 输入 输出 一开始用了一个栈,写着写着嵌套的逻辑卡住了,最后用俩stack解决。。然后follow-up问的是不要输出string而是输出解压后的K-th character,主要也还是嵌套情况就从内到外把疙瘩解开以后再算。。然后我问俩问题就结束了。整体感觉妹子面试官人很nice 反应很快而且不是特别picky的那种。
变种2:
“3a2[mtv]ac”, decompress to: aaamtvmtvac,括号可以嵌套。 这个我觉得不是很难,大概花了15分钟理清了思路并写好了代码,大概就是找匹配括号递归解,面试官也找不到bug表示认同。
但吊诡的地方来了,面试官说把这种字符串compress回去...这显然有多种情况,于是我问是不是要求压缩后最短,面试官说肯定越短越好。 比如对于aaaa, 肯定4a比2[aa]好。
Last updated
Was this helpful?