字符串排序 | 青训营X豆包MarsCode 技术训练营

26 阅读6分钟

原题:

小C需要对一个字符串进行特殊排序,这个字符串只包含三种字符类型:字母(大小写)、数字和问号。要求你按照以下规则进行排序: 1.问号的原始位置必须保持不变, 2.数字的原始位置必须保持不变,但数字要按照从大到小排序. 3.字母的原始位置必须保持不变,但字母要按照字典序从小到大排序. 你需要编写一个程序,帮助小C实现这个字符串的排序功能。

根据题目要求,我们需要对字符串中的字母、数字和问号进行特定的排序。以下是详细的思路和步骤。

思路:

  1. 问号位置保持不变:我们不能对问号的位置进行移动,因此,首先需要记录问号的位置。
  2. 数字按从大到小排序:所有的数字需要按照从大到小的顺序排列,但它们的相对位置不能改变。
  3. 字母按字典序从小到大排序:所有的字母需要按照字典序(ASCII顺序)从小到大排列,同样,它们的相对位置不能改变。

步骤:

  1. 首先遍历字符串,将字母、数字和问号分别提取出来。
  2. 对数字和字母进行排序:
    • 对数字进行从大到小排序。
    • 对字母进行从小到大排序。
  3. 然后将数字、字母和问号重新按原位置进行组装。

代码实现:

def solution(inp):
    # Step 1: 提取字母、数字和问号
    letters = []
    digits = []
    question_marks = []
    
    for ch in inp:
        if ch.isalpha():
            letters.append(ch)
        elif ch.isdigit():
            digits.append(ch)
        elif ch == '?':
            question_marks.append(ch)
    
    # Step 2: 对字母和数字排序
    letters.sort()  # 字母按字典序从小到大
    digits.sort(reverse=True)  # 数字按从大到小排序
    
    # Step 3: 重新构造结果
    result = []
    letter_idx = 0
    digit_idx = 0
    question_idx = 0
    
    for ch in inp:
        if ch == '?':
            result.append('?')  # 保持问号位置不变
            question_idx += 1
        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. 提取字符
    • 我们遍历输入字符串,并通过判断字符的类型(字母、数字、问号),将它们分别放入lettersdigitsquestion_marks列表中。
  2. 排序
    • 对字母列表letters进行升序排序(字典序)。
    • 对数字列表digits进行降序排序。
  3. 重建字符串
    • 我们重新遍历原始输入字符串,根据原来的字符类型将排序后的字母和数字按正确的位置填入结果中,保持问号的位置不变。

复杂度分析:

  • 时间复杂度:遍历字符串一次是 O(n),字母和数字的排序分别是 O(n log n),因此整体时间复杂度为 O(n log n),其中 n 是字符串的长度。
  • 空间复杂度:需要额外的存储来存放字母、数字和问号,空间复杂度为 O(n)。

测试:

print(solution("12A?zc") == "21A?cz")   # 输出: True
print(solution("1Ad?z?t24") == "4Ad?t?z21")  # 输出: True
print(solution("???123??zxy?") == "???321??xyz?")  # 输出: True

这段代码实现了题目要求的功能,能够正确地处理各种字符,并按照题目要求对字母和数字进行排序,同时保留问号的原始位置。 根据题目要求,我们需要对字符串中的字母、数字和问号进行特定的排序。以下是详细的思路和步骤。

思路:

  1. 问号位置保持不变:我们不能对问号的位置进行移动,因此,首先需要记录问号的位置。
  2. 数字按从大到小排序:所有的数字需要按照从大到小的顺序排列,但它们的相对位置不能改变。
  3. 字母按字典序从小到大排序:所有的字母需要按照字典序(ASCII顺序)从小到大排列,同样,它们的相对位置不能改变。

步骤:

  1. 首先遍历字符串,将字母、数字和问号分别提取出来。
  2. 对数字和字母进行排序:
    • 对数字进行从大到小排序。
    • 对字母进行从小到大排序。
  3. 然后将数字、字母和问号重新按原位置进行组装。

代码实现:

def solution(inp):
    # Step 1: 提取字母、数字和问号
    letters = []
    digits = []
    question_marks = []
    
    for ch in inp:
        if ch.isalpha():
            letters.append(ch)
        elif ch.isdigit():
            digits.append(ch)
        elif ch == '?':
            question_marks.append(ch)
    
    # Step 2: 对字母和数字排序
    letters.sort()  # 字母按字典序从小到大
    digits.sort(reverse=True)  # 数字按从大到小排序
    
    # Step 3: 重新构造结果
    result = []
    letter_idx = 0
    digit_idx = 0
    question_idx = 0
    
    for ch in inp:
        if ch == '?':
            result.append('?')  # 保持问号位置不变
            question_idx += 1
        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. 提取字符
    • 我们遍历输入字符串,并通过判断字符的类型(字母、数字、问号),将它们分别放入lettersdigitsquestion_marks列表中。
  2. 排序
    • 对字母列表letters进行升序排序(字典序)。
    • 对数字列表digits进行降序排序。
  3. 重建字符串
    • 我们重新遍历原始输入字符串,根据原来的字符类型将排序后的字母和数字按正确的位置填入结果中,保持问号的位置不变。

复杂度分析:

  • 时间复杂度:遍历字符串一次是 O(n),字母和数字的排序分别是 O(n log n),因此整体时间复杂度为 O(n log n),其中 n 是字符串的长度。
  • 空间复杂度:需要额外的存储来存放字母、数字和问号,空间复杂度为 O(n)。

测试:

print(solution("12A?zc") == "21A?cz")   # 输出: True
print(solution("1Ad?z?t24") == "4Ad?t?z21")  # 输出: True
print(solution("???123??zxy?") == "???321??xyz?")  # 输出: True

这段代码实现了题目要求的功能,能够正确地处理各种字符,并按照题目要求对字母和数字进行排序,同时保留问号的原始位置。