跳转至

271. 字符串的编码与解码 🔒

题目描述

请你设计一个算法,可以将一个 字符串列表 编码成为一个 字符串。这个编码后的字符串是可以通过网络进行高效传送的,并且可以在接收端被解码回原来的字符串列表。

1 号机(发送方)有如下函数:

string encode(vector<string> strs) {
  // ... your code
  return encoded_string;
}

2 号机(接收方)有如下函数:

vector<string> decode(string s) {
  //... your code
  return strs;
}

1 号机(发送方)执行:

string encoded_string = encode(strs);

2 号机(接收方)执行:

vector<string> strs2 = decode(encoded_string);

此时,2 号机(接收方)的 strs2 需要和 1 号机(发送方)的 strs 相同。

请你来实现这个 encode 和 decode 方法。

不允许使用任何序列化方法解决这个问题(例如 eval)。

 

示例 1:

输入:dummy_input = ["Hello","World"]
输出:["Hello","World"]
解释:
1 号机:
Codec encoder = new Codec();
String msg = encoder.encode(strs);
Machine 1 ---msg---> Machine 2

2 号机:
Codec decoder = new Codec();
String[] strs = decoder.decode(msg);

示例 2:

输入:dummy_input = [""]
输出:[""]

 

提示:

  • 1 <= strs.length <= 200
  • 0 <= strs[i].length <= 200
  • strs[i] 包含 256 个有效 ASCII 字符中的任何可能字符。

 

进阶:你能编写一个通用算法来处理任何可能的字符集吗?

解法

方法一:编码字符串长度

编码时,将字符串的长度转成固定 $4$ 位的字符串,加上字符串本身,依次拼接到结果字符串。

解码时,先取前四位字符串,得到长度,再通过长度截取后面的字符串。依次截取,最终得到字符串列表。

时间复杂度 $O(n)$。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Codec:
    def encode(self, strs: List[str]) -> str:
        """Encodes a list of strings to a single string."""
        ans = []
        for s in strs:
            ans.append('{:4}'.format(len(s)) + s)
        return ''.join(ans)

    def decode(self, s: str) -> List[str]:
        """Decodes a single string to a list of strings."""
        ans = []
        i, n = 0, len(s)
        while i < n:
            size = int(s[i : i + 4])
            i += 4
            ans.append(s[i : i + size])
            i += size
        return ans


# Your Codec object will be instantiated and called as such:
# codec = Codec()
# codec.decode(codec.encode(strs))
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class Codec {

    // Encodes a list of strings to a single string.
    public String encode(List<String> strs) {
        StringBuilder ans = new StringBuilder();
        for (String s : strs) {
            ans.append((char) s.length()).append(s);
        }
        return ans.toString();
    }

    // Decodes a single string to a list of strings.
    public List<String> decode(String s) {
        List<String> ans = new ArrayList<>();
        int i = 0, n = s.length();
        while (i < n) {
            int size = s.charAt(i++);
            ans.add(s.substring(i, i + size));
            i += size;
        }
        return ans;
    }
}

// Your Codec object will be instantiated and called as such:
// Codec codec = new Codec();
// codec.decode(codec.encode(strs));
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Codec {
public:
    // Encodes a list of strings to a single string.
    string encode(vector<string>& strs) {
        string ans;
        for (string s : strs) {
            int size = s.size();
            ans += string((const char*) &size, sizeof(size));
            ans += s;
        }
        return ans;
    }

    // Decodes a single string to a list of strings.
    vector<string> decode(string s) {
        vector<string> ans;
        int i = 0, n = s.size();
        int size = 0;
        while (i < n) {
            memcpy(&size, s.data() + i, sizeof(size));
            i += sizeof(size);
            ans.push_back(s.substr(i, size));
            i += size;
        }
        return ans;
    }
};

// Your Codec object will be instantiated and called as such:
// Codec codec;
// codec.decode(codec.encode(strs));
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
type Codec struct {
}

// Encodes a list of strings to a single string.
func (codec *Codec) Encode(strs []string) string {
    ans := &bytes.Buffer{}
    for _, s := range strs {
        t := fmt.Sprintf("%04d", len(s))
        ans.WriteString(t)
        ans.WriteString(s)
    }
    return ans.String()
}

// Decodes a single string to a list of strings.
func (codec *Codec) Decode(strs string) []string {
    ans := []string{}
    i, n := 0, len(strs)
    for i < n {
        t := strs[i : i+4]
        i += 4
        size, _ := strconv.Atoi(t)
        ans = append(ans, strs[i:i+size])
        i += size
    }
    return ans
}

// Your Codec object will be instantiated and called as such:
// var codec Codec
// codec.Decode(codec.Encode(strs));

评论