题目链接:Base32 编码和解码问题 - MarsCode
题目描述
实现 Base32 的编码和解码函数。Base32 编码以 5 位为一组,将二进制数据映射到字符表,用于将二进制数据表示为字符串。输入数据若不足 5 的倍数位则需补零,编码后按长度需求在末尾补 + 符号。解码时去除 + 符号,解析还原出原始数据。
问题分析
- 编码流程:
- 将字符串转换为二进制。
- 若长度不满 5 的倍数则补零。
- 将二进制串以 5 位为一组转换为索引,映射到对应字符。
- 根据原始字符串长度在末尾补
+。
- 解码流程:
- 将字符串拆成可以解码的子串, 比如"bljhy+++b0zj5+++"先拆成"bljhy+++","b0zj5+++"。
- 对于每个子串:
- 统计
+的数量,得到原始数据末尾有几个0。 - 将每个字符映射到对应索引,索引转换为二进制形式并补全。
- 去除末尾的0,每8位还原成ASCII字符。
- 统计
解题思路
-
主函数
solution:- 调用
encode和decode函数。 - 对编码字符串调用
encode;对解码字符串进行拆分,分别调用decode然后拼接。 - 结果格式为编码和解码结果的拼接输出。
- 调用
-
编码函数
encode:- 使用
convert_string_to_binary将输入字符串转为二进制字符串。 - 若不为 5 的倍数则用
completeChar补零。 - 每 5 位分组,通过
get_char_by_index查找字符映射。 - 对生成字符串补
+。
- 使用
-
解码函数
decode:- 统计
+数量,并将字符转为 5 位二进制索引。 - 根据
+数量确定尾部需去掉的多余零,得到原始数据。 - 将二进制数据按 8 位分组,并转换为 ASCII 字符,拼接成结果。
- 统计
-
辅助函数:
completeChar用于将字符串长度补齐为指定的倍数。convert_string_to_binary将字符串逐字符转换成二进制串。get_char_by_index和get_index_by_char分别实现字符和索引间的查找。
代码实现
def solution(rawStr, encodedStr):
encodeStr = encode(rawStr)
decodeStr = ""
start = 0
for i in range(len(encodedStr)):
if (encodedStr[i] == '+' and i+1 >= len(encodedStr) or (encodedStr[i] == '+' and encodedStr[i+1] != '+')):
subStr = encodedStr[start:i + 1]
start = i + 1
decodeStr += decode(subStr)
return encodeStr + ":" + decodeStr
def encode(str):
bStr = convert_string_to_binary(str)
bStr = completeChar(bStr, 5, '0')
result = ""
for i in range(0, len(bStr), 5):
subStr = bStr[i:i+5]
index = int(subStr, 2)
result += get_char_by_index(index)
result = completeChar(result, 8, '+')
return result
def decode(eStr):
bStr = ""
plusNum = 0
plus_rest = {0: 0, 6: 8, 4: 16, 3: 24, 1: 32}
for c in eStr:
if c == '+':
plusNum += 1
continue
index = get_index_by_char(c)
decimal = bin(index)[2:].zfill(5)
bStr += str(decimal)
rest = plus_rest[plusNum]
zeroNum = (len(bStr) % 40) - rest
bStr = bStr[:-zeroNum]
result = ""
for i in range(0, len(bStr), 8):
subStr = bStr[i:i+8]
code = int(subStr, 2)
result += chr(code)
return result
def completeChar(str,num,char):
rest = len(str) % num
if(rest != 0):
str = str + char*(num-rest)
return str
def convert_string_to_binary(s):
binary_str = ""
for char in s:
ascii_code = ord(char)
binary_code = bin(ascii_code)[2:].zfill(8)
binary_str += binary_code
return binary_str
index_char_mapping = {
0: '9',
1: '8',
2: '7',
3: '6',
4: '5',
5: '4',
6: '3',
7: '2',
8: '1',
9: '0',
10:'m',
11: 'n',
12: 'b',
13: 'v',
14: 'c',
15: 'x',
16: 'z',
17: 'a',
18:'s',
19: 'd',
20: 'f',
21: 'g',
22: 'h',
23: 'j',
24: 'k',
25: 'l',
26: 'p',
27: 'o',
28: 'i',
29: 'u',
30: 'y',
31: 't'
}
# 通过索引查字符
def get_char_by_index(index):
return index_char_mapping[index]
# 通过字符查索引
def get_index_by_char(char):
for key, value in index_char_mapping.items():
if value == char:
return key
return -1 # 表示未找到
复杂度分析
- 时间复杂度:编码和解码都需遍历字符串,为 (O(n))。
- 空间复杂度:二进制数据存储所需空间为 (O(n))。
总结与收获
该题考察了对字符串二进制编码的实现及位操作技巧,通过处理字符串补零、按位分组和查找索引的方式,加深了对字符编码规则的理解。