字符串的编码与解码 图解题解
把一堆字符串拼成一条再拆回来,难点在于分隔符可能出现在内容里——长度前缀是最干净的解法。
物流公司打包多件货物时,不能直接用逗号隔开货物名——万一货物名里本身就有逗号就乱套了。正确做法是在每件货物外面套一个「长度标签」:先写这件货物有多少字,再写货物内容。收货方先看标签知道取几个字,精确拆包,完全不怕内容里有任何特殊字符。这题的 len# 前缀,就是那个长度标签。
这道题到底在问什么
- 示例
- strs=["lint","code","love"] → 解码后仍是原数组
最优解:一步一步想明白
- 3直接用逗号拼接会被字符串里的逗号骗到。
- 4每个字符串前写长度和分隔符,解码时先读长度,再按长度切片。
- 5编码核心:在每段前面放「长度 + #」,告诉解码器这段有多长。
- 6拼接后无需逗号分隔——长度前缀自带边界信息。
- 7先读长度:一直读数字直到遇见 #。
- 8按长度精确切 len 个字符,再把指针挪到下一段。
- 9循环「读长度→切内容→跳指针」,直到字符串读完。
- 12一句话记住:每个字符串前写长度和分隔符,解码时先读长度,再按长度切片。
- 15分隔符会和内容撞车;长度前缀读固定个数,永不歧义。
- 22这题学完不要乱跳,下一步去对应专题 /leetcode-animation/ds?k=hashtable 连刷同类题;卡住时用 AI 答疑问“长度前缀为什么对任意字符都安全”。
⚠️ 容易写错的地方
✗ 错:用逗号 / # 等分隔符直接拼接
✓ 对:用「长度#内容」前缀编码
字符串内可能含任何字符(包括分隔符),分隔符法会切错;长度前缀读恰好 len 个字符,绝不歧义。
✗ 错:把长度数字按单个字符读
✓ 对:一直读到 # 前的整段数字才是长度
长度可能多位(如 12#),要读到 # 才停,否则切错。
✗ 错:空串 / 空数组没处理
✓ 对:空串写成 0#,空数组编码为空字符串
0# 能表示长度为 0 的串,解码切出空串;空数组编码后为 ""。
完整代码(Python / C++ / Java)
Python
class Codec:
def encode(self, strs):
return "".join(f"{len(s)}#{s}" for s in strs)
def decode(self, s):
ans, i = [], 0
while i < len(s):
j = s.find("#", i); size = int(s[i:j])
ans.append(s[j+1:j+1+size]); i = j + 1 + size
return ansC++
class Codec {
public:
string encode(vector<string>& strs) {
string out;
for (auto& s: strs) out += to_string(s.size()) + "#" + s;
return out;
}
vector<string> decode(string s) {
vector<string> ans; int i = 0;
while (i < s.size()) {
int j = s.find("#", i), len = stoi(s.substr(i, j-i));
ans.push_back(s.substr(j+1, len)); i = j + 1 + len;
}
return ans;
}
};Java
public class Codec {
public String encode(List<String> strs) {
StringBuilder sb = new StringBuilder();
for (String s: strs) sb.append(s.length()).append("#").append(s);
return sb.toString();
}
public List<String> decode(String s) {
List<String> ans = new ArrayList<>(); int i = 0;
while (i < s.length()) {
int j = s.indexOf("#", i), len = Integer.parseInt(s.substring(i, j));
ans.add(s.substring(j+1, j+1+len)); i = j + 1 + len;
} return ans;
}
}套路模板 · 长度前缀编解码骨架
# 长度前缀 编码/解码 骨架
def encode(strs):
return "".join(f"{len(s)}#{s}" for s in strs)
def decode(s):
res, i = [], 0
while i < len(s):
j = s.index("#", i) # 找到长度后的 #
length = int(s[i:j]) # 读出长度
res.append(s[j+1 : j+1+length]) # 切 length 个字符
i = j + 1 + length # 跳到下一段
return res复杂度
时间复杂度
O(n)
编码、解码各扫一遍全部字符 N
空间复杂度
O(n)
输出字符串与原文等长
看不够?换成动画再走一遍
上面的推演每一步都对应一帧动画。点开交互动画版,能一步步看着 字符串的编码与解码 的数据怎么变、指针怎么走,还能切 Python / Java / C++ 跟着练。
面试官可能追问
整体思路是什么?+
编码:每个串写成 len(s)+"#"+s 后首尾拼接。解码:指针从头走,先读数字到 # 得长度 len,再从 # 后取 len 个字符作为一个串,指针跳过这段,重复直到读完。
这道题为什么用「哈希」,换最直接的暴力解会差在哪?+
哈希抓住了本题的结构特征,把暴力解里重复的工作省掉;暴力解通常要多嵌套一层枚举,数据一大就超时。具体对比见上文「暴力解及其卡点」与「最优解逐步推演」两节。
本平台为独立第三方培训机构,与华为技术有限公司无任何关联;课程的服务内容与权益以购买协议为准,学习效果因个人情况而异。「华为 OD」「华为可信」等仅为对岗位与考试方向的客观描述,相关商标归各自权利人所有。