编码和解码字符串

题目:实现字符串数组到字符串的序列化和反序列化方法,使得输入的字符串数组经过一次编码和一次解码后,仍和原来保持一致。

string encode(vector<string>& strs) {}

vector<string> decode(string s) {}  

题解

遍历字符串数组,计算每个元素的长度,增加到字符串开头,并增加一个特殊界定符,用于隔开长度和原始字符串:str.size() + '#' + str

字符串中出现了 '#' 符号会不会有影响?

答案是不会,关键在于 '#' 第一次出现的位置,这是可以确定的,然后将位置左边的内容解析为长度值,位置往右数长度值个字符的内容解析为原始字符串。

看一个例子就比较清晰了:

5 # h e # # o 5 # w o r l d
  ^             ^
  首个 # 位置   

找到首个 # 位置,解析长度为 5 ,往 # 位置后数 5 个字符,解析字符串为 "he##o"。也就是说,原始字符串中存在 # 符号也不会有任何影响,会被完整解析为字符串。

依此类推直到最后一个字符串。这里需要使用的一个技巧是:解析完第一个字符串后,将这部分内容删除,使得解析后续字符串都如同首个一样。

代码

string encode(vector<string>& strs) {
    string ret = "";
    for (string str : strs) {
        ret += to_string(str.length()) + "#" + str; 
    }
    return ret;
}

vector<string> decode(string s) {
    vector<string> ret = {};
    while (!s.empty()) {
        if (s.find("#") != string::npos) {
            int pos = s.find("#");
            size_t len = stoi(s.substr(0, pos));
            ret.push_back(s.substr(pos + 1, len));
            s.erase(0, s.substr(0, pos).length() + 1 + len);
        }
    }
    return ret;
}

历程

相较于其他算法题,这更像是一个程序员日常需要解决的工程问题。

一上来没想那么多,直接使用逗号分隔符号连接字符串数组。很明显,这种方法不能通过测试用例包含逗号分隔符的情况,失败。

查看提示,了解到可以通过记录字符串长度进行标识,如何记录字符串长度信息成为关键。但我马上又遇到新的问题;长度本身也占不定长度字符,不好解析。

再次审题,发现每个字符串的长度不会超过 200,也就是说三位数字就足以存储所有可能的字符串(不满三位时补充0)。在解析字符串时,前三位固定为长度值,紧接着为原始字符串。很幸运,通过测试。

反思,但如果字符串是任意长度,代码就不适应了。查看答案,发现只要在长度和字符串之间增加一个特定符号就可以解决。妙!

链接

  • https://neetcode.io/problems/string-encode-and-decode/question