跳到主要内容

HJ30. 字符串合并处理

题目描述​

给定两个字符串 s1、s2(由大小写字母和数字构成,下标从 1 开始)。

【合并阶段】

  1. 将 s1、s2 合并得到新串 str2。
  2. 将 str2 中奇数位字符按 ASCII 码升序排序,偶数位字符也按 ASCII 码升序排序,得到 str3。

【调整阶段】 从左到右遍历 str3 的每个字符:

  1. 若字符不是合法十六进制字符(0-9、a-f、A-F),原样保留;
  2. 否则转十进制数,转成四位二进制(高位补 0),翻转二进制,再转回大写十六进制。

输入格式​

  • 一行两个字符串 s1 s2(用空格分隔)。

输出格式​

  • 处理后的最终字符串。

示例​

示例 1​

输入:

dec fab

输出:

5D37BF

说明: 合并得 decfab,奇数位排序后与偶数位排序交错得到 dcefba,再逐个十六进制反转:d→B、c→3、e→7、f→F、b→D、a→5 → 5D37BF。

示例 2​

输入:

abV CDw

输出:

B3VD5w

解题思路​

第一步:理解问题本质​

分为两个阶段:先做奇偶位分离排序,再对十六进制字符做二进制反转。

第二步:暴力解法(逐字符排序拼接)​

合并后用一个循环模拟奇数位、偶数位分别提取再排序。

问题:下标(1 基)容易混淆,需要仔细对齐奇数位/偶数位。

第三步:优化解法(切片分离 + sorted)​

利用切片 [0::2] 和 [1::2] 直接提取所有奇数位(1 基奇数位 = 0 基偶数下标)和偶数位,分别 sorted() 后再交错拼回。

odd = sorted(merged[0::2])    # 1基奇数位 = 0基偶数
even = sorted(merged[1::2]) # 1基偶数位 = 0基奇数
inter = []
for i in range(len(merged)):
inter.append(odd[i // 2] if i % 2 == 0 else even[i // 2])
str3 = ''.join(inter)

第四步:最优解法(十六进制转换)​

调整阶段对每个字符:用 int(ch, 16) 判断是否为合法十六进制字符(非法会抛异常),合法则转四位二进制、反转、再转回大写十六进制。

def transform(ch: str) -> str:
try:
val = int(ch, 16) # 非法十六进制会抛异常
except ValueError:
return ch
rev = format(val, '04b')[::-1] # 转四位二进制、反转
return hex(int(rev, 2))[2:].upper()

完整代码实现​

算法可视化 · 逐帧回放这道题的代码9 帧 · 录制输入
import sys


def transform(ch: str) -> str:
"""调整阶段:十六进制字符反转二进制后转回大写十六进制,非十六进制字符保留"""
try:
val = int(ch, 16) # 非法十六进制会抛异常
except ValueError:
return ch
# 转四位二进制、反转、再转回十六进制大写
rev = format(val, '04b')[::-1]
return hex(int(rev, 2))[2:].upper()


def solve() -> None:
"""主求解函数"""
s1, s2 = sys.stdin.readline().split()
merged = s1 + s2

# 合并阶段:奇数位、偶数位分别按 ASCII 升序排序后交错拼回(下标从 1 开始)
odd = sorted(merged[0::2]) # 1基奇数位 = 0基偶数
even = sorted(merged[1::2]) # 1基偶数位 = 0基奇数
inter = []
for i in range(len(merged)):
inter.append(odd[i // 2] if i % 2 == 0 else even[i // 2])
str3 = ''.join(inter)

# 调整阶段
print(''.join(transform(c) for c in str3))


if __name__ == "__main__":
solve()

示例推演​

以示例 1 dec fab 为例:

合并阶段:

  1. 合并 dec + fab = decfab
  2. 奇数位(1 基):d、c、f(0 基下标 0、2、4)→ 排序后 c d f
  3. 偶数位(1 基):e、a、b(0 基下标 1、3、5)→ 排序后 a b e
  4. 交错拼回:d c e f a b 对应位置取值 → d c e f a b,即 dcefab

(注:排序后奇数位为 c,d,f,偶数位为 a,b,e,交错到 1 基奇/偶位得到 d c e f a b → dcefab)

调整阶段:

字符合法十六进制?二进制反转十六进制
d是11011011B
c是110000113
e是111001117
f是11111111F
a是101001015
b是10111101D

拼接结果:B 3 7 F 5 D → 5D37BF。


复杂度分析​

解法时间复杂度空间复杂度说明
逐字符模拟排序O(L log L)O(L)排序开销,下标易错
切片 + 转换O(L log L)O(L)切片与 sorted 简洁

L 为合并后字符串长度


易错点总结​

1. 奇偶位下标​

题目下标从 1 开始,1 基奇数位对应 0 基偶数下标,容易混淆。

2. 非十六进制字符保留​

只有合法十六进制字符(0-9、a-f、A-F)才做二进制反转,其余(如 g、Z、V)原样保留。

3. 二进制补位与反转​

十六进制转二进制要补足 4 位,反转后再转回十六进制,注意输出大写。

4. 排序按 ASCII 升序​

奇数位、偶数位分别按 ASCII 码升序排序,不是按字符对应的数值。


扩展思考​

  • 用 int(ch, 16) 判断合法性并取值,巧妙复用了异常处理。
  • 十六进制与二进制的转换可借助 Python 的 format 与 int(x, base) 完成,注意 4 位补零。

相关题目​

自测​

加载评论中...