字符串字符类型排序问题 | 豆包MarsCode AI 刷题

62 阅读3分钟

问题解析

在这个问题中,我们需要对包含 字母、数字、问号 的字符串进行排序,并遵循以下规则:

  1. 问号位置不变:问号在原字符串中的位置必须保持不变。
  2. 数字排序:数字在字符串中的位置固定,但需要按照从大到小的顺序排序。
  3. 字母排序:字母在字符串中的位置固定,但需要按照字典序从小到大排序(大小写敏感,即 'A' < 'a')。

我们需要设计一个算法实现这些规则,同时保证字符串结构的正确性。


解题思路

为了解决这个问题,我们可以分为以下几个步骤:

1. 提取不同类型的字符
  • 遍历字符串,将其分为三类:数字字母问号

    • 数字:通过 isdigit() 判断。
    • 字母:通过 isalpha() 判断。
    • 问号:通过直接比较字符是否为 '?' 判断。
  • 将提取的数字和字母存入两个列表,问号无需特殊处理,只需记录其在原字符串中的位置即可。

2. 对提取的字符排序
  • 数字:使用 sort(reverse=True) 对数字列表进行降序排序。
  • 字母:使用 sort() 对字母列表进行升序排序。
  • 问号:无需排序,因为位置不变。
3. 重构字符串
  • 遍历原字符串,逐字符检查:

    • 如果是问号,直接保留原字符。
    • 如果是数字,从排序后的数字列表中取出一个数字替换。
    • 如果是字母,从排序后的字母列表中取出一个字母替换。
  • 将所有字符按顺序拼接,生成最终结果。

4. 时间复杂度分析
  • 字符分类(提取数字、字母、问号):时间复杂度为 O(n),其中 n是字符串长度。
  • 排序数字和字母:时间复杂度分别为 O(klog⁡k)和 O(mlog⁡m),其中 k 是数字的数量,m 是字母的数量。
  • 字符替换:遍历一次字符串,时间复杂度为 O(n)。
  • 综合时间复杂度为 O(n+klog⁡k+mlog⁡m),效率较高。

实现代码

以下是完整的代码实现:

def solution(inp):
    # Step 1: 分别提取数字、字母和问号
    digits = [ch for ch in inp if ch.isdigit()]
    letters = [ch for ch in inp if ch.isalpha()]
    
    # Step 2: 排序数字和字母
    digits.sort(reverse=True)  # 数字降序排序
    letters.sort()  # 字母升序排序
    
    # Step 3: 创建结果字符串,保持问号位置不变
    result = []
    digit_idx, letter_idx = 0, 0
    
    for ch in inp:
        if ch == '?':
            result.append('?')
        elif ch.isdigit():
            result.append(digits[digit_idx])
            digit_idx += 1
        elif ch.isalpha():
            result.append(letters[letter_idx])
            letter_idx += 1
    
    return ''.join(result)

# 测试代码
if __name__ == "__main__":
    print(solution("12A?zc") == "21A?cz")
    print(solution("1Ad?z?t24") == "4Ad?t?z21")
    print(solution("???123??zxy?") == "???321??xyz?")

总结与反思

关键点
  1. 字符串的分类提取:利用内置方法 isdigit()isalpha() 快速区分数字和字母。
  2. 排序规则:数字降序,字母升序,符合题目要求。
  3. 保持问号位置不变:通过遍历原字符串,逐步替换字符,确保问号位置正确。
可扩展性
  • 如果需要支持更多类型的字符(如特殊符号),只需添加分类和排序逻辑。
  • 对于更复杂的排序规则,可以将提取字符、排序和替换的逻辑进一步封装成独立模块。
优化空间
  • 本代码已经优化了时间复杂度,但对于特别大的字符串(如数万字符)仍需测试性能。
  • 可以使用计数排序优化部分逻辑(如对数字的排序)。