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

62 阅读3分钟

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

字符串字符类型排序问题 - MarsCode

题目规则不清,大写字母要排在小写字母前。简单模拟,用队列思想解决。

摘要

本文介绍了如何对一个字符串按指定规则排序。字符串包含字母、数字和问号。排序规则为数字从大到小、字母按字典序从小到大,并且字符类型的位置保持不变。本文包含Python和Go的代码实现,算法时间复杂度为 O(nlogn)O(n \log n)

问题描述

在一个仅包含字母、数字和问号的字符串中,需要按如下规则排序:

  1. 问号位置不变。
  2. 数字按降序排序。
  3. 字母按字典序升序排序。

示例

  • 输入:inp = "12A?zc" 输出:"21A?cz"

  • 输入:inp = "1Ad?z?t24" 输出:"4Ad?t?z21"

  • 输入:inp = "???123??zxy?" 输出:"???321??xyz?"

原理分析

1. 字符分类

遍历字符串,将字符分为三类:数字、大写字母、小写字母,并各自存进一个切片进行自定义的排序。

2. 排序规则

对每个分类的字符按照指定的顺序排序:

  • 数字按从大到小排序。
  • 字母按字典序从小到大排序。

3. 构建结果字符串

根据原字符串的位置,将排序后的字符填充到对应位置,问号保留不变。用取队头的方式进行取元素放入答案字符串里面,保持元素的排序后的先后顺序不变。在大小写字母的处理上要判断大写字母是否已经消耗完毕,再考虑使用哪一个队列(大写字母或者小写字母)

代码实现

Python代码

from typing import List

def solution(inp: str) -> str:
    """
    该函数接收一个字符串 inp,对其中的数字、大小写字母进行排序:
    - 数字按降序排列
    - 大写字母和小写字母分别按升序排列
    返回按照原始字符类型排列好的新字符串
    """
    nums = []
    chars_up = []
    chars_do = []

    # 遍历字符串并分类
    for ch in inp:
        if '0' <= ch <= '9':
            nums.append(int(ch))
        elif 'A' <= ch <= 'Z':
            chars_up.append(ch)
        elif 'a' <= ch <= 'z':
            chars_do.append(ch)

    # 对每个分类分别排序
    chars_up.sort()
    chars_do.sort()
    nums.sort(reverse=True)

    # 用于构造最终字符串的列表
    ans_str = []
    num_index, up_index, do_index = 0, 0, 0

    # 根据原始字符类型填充排序后的字符
    for ch in inp:
        if '0' <= ch <= '9':
            ans_str.append(str(nums[num_index]))
            num_index += 1
        elif 'A' <= ch <= 'Z':
            ans_str.append(chars_up[up_index])
            up_index += 1
        elif 'a' <= ch <= 'z':
            ans_str.append(chars_do[do_index])
            do_index += 1
        else:
            ans_str.append('?')

    return ''.join(ans_str)


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

Go语言代码

package main

import (
	"fmt"
	"sort"
)

func solution(inp string) string {
	nums := []int{}
	charsUp := []rune{}
	charsDo := []rune{}

	// 分类字符
	for i := 0; i < len(inp); i++ {
		if inp[i] >= '0' && inp[i] <= '9' {
			nums = append(nums, int(inp[i]-'0'))
		} else if inp[i] >= 'A' && inp[i] <= 'Z' {
			charsUp = append(charsUp, rune(inp[i]))
		} else if inp[i] >= 'a' && inp[i] <= 'z' {
			charsDo = append(charsDo, rune(inp[i]))
		}
	}

	// 排序
	sort.Slice(charsUp, func(i, j int) bool {
		return charsUp[i] < charsUp[j]
	})
	sort.Slice(charsDo, func(i, j int) bool {
		return charsDo[i] < charsDo[j]
	})
	sort.Slice(nums, func(i, j int) bool {
		return nums[i] > nums[j]
	})

	// 构建结果
	ansStr := []rune{}
	for i := 0; i < len(inp); i++ {
		if inp[i] >= '0' && inp[i] <= '9' {
			ansStr = append(ansStr, rune(nums[0]+'0'))
			nums = nums[1:]
		} else if inp[i] >= 'A' && inp[i] <= 'Z' {
			ansStr = append(ansStr, charsUp[0])
			charsUp = charsUp[1:]
		} else if inp[i] >= 'a' && inp[i] <= 'z' {
			ansStr = append(ansStr, charsDo[0])
			charsDo = charsDo[1:]
		} else {
			ansStr = append(ansStr, '?')
		}
	}
	return string(ansStr)
}

func main() {
	// 测试用例
	fmt.Println(solution("12A?zc") == "21A?cz")
	fmt.Println(solution("1Ad?z?t24") == "4Ad?t?z21")
	fmt.Println(solution("???123??zxy?") == "???321??xyz?")
}