基数排序的进阶应用:对包含负数的整数数组进行排序
字数 1095 2025-11-11 23:33:10
基数排序的进阶应用:对包含负数的整数数组进行排序
题目描述
给定一个包含正数、负数和零的整数数组,要求使用基数排序(Radix Sort)对数组进行升序排序。例如,输入数组为 [170, -45, 75, -90, 2, -802, 24],排序后应得到 [-802, -90, -45, 2, 24, 75, 170]。
解题过程
步骤1:理解基数排序的局限性
基数排序通常用于非负整数排序,其核心思想是按数位(个位、十位、百位等)进行稳定排序(如计数排序)。但负数存在时,直接按位排序会导致错误结果,因为负数的最高位(符号位)在二进制补码表示中与其他位含义不同。
步骤2:处理负数的关键思路
- 分离正数和负数:将数组分为负数和非负数(包括零)两部分。
- 分别处理负数:
- 对负数部分取绝对值,然后使用基数排序按位排序。
- 由于负数绝对值越大,实际值越小(如
-90比-45小),排序后的负数部分需要反转顺序。
- 合并结果:将反转后的负数部分与非负数部分拼接。
步骤3:具体实现步骤
-
分离正负数:
- 遍历数组,将负数存入列表
negative,非负数存入列表non_negative。 - 示例:
输入: [170, -45, 75, -90, 2, -802, 24] negative: [-45, -90, -802] non_negative: [170, 75, 2, 24]
- 遍历数组,将负数存入列表
-
对负数部分排序:
- 将
negative中每个数取绝对值:[45, 90, 802]。 - 使用基数排序对该列表排序(按个位、十位、百位等):
- 个位排序:
[90, 802, 45]→ 按十位:[802, 45, 90]→ 按百位:[45, 90, 802]。
- 个位排序:
- 将排序后的绝对值列表反转(因为负数需要按绝对值降序):
[802, 90, 45]。 - 恢复负号:
[-802, -90, -45]。
- 将
-
对非负数部分排序:
- 直接使用基数排序对
non_negative排序,得到[2, 24, 75, 170]。
- 直接使用基数排序对
-
合并结果:
- 将负数部分
[-802, -90, -45]与非负数部分[2, 24, 75, 170]拼接,得到最终结果。
- 将负数部分
步骤4:基数排序的位处理优化
- 对于负数绝对值排序,需统一数位长度(如补零到最大数字的位数),避免比较时出错。
- 实际代码中可通过计算最大绝对值确定需要处理的位数。
步骤5:复杂度分析
- 时间复杂度:
O(d * (n + k)),其中d为最大位数,k为基数(通常取10),n为数组长度。 - 空间复杂度:
O(n + k),用于计数排序的临时数组和桶。
总结
通过分离正负数、分别处理并合并,基数排序可高效支持包含负数的整数排序,且保持稳定性与线性时间复杂度。