You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改归并排序实现仅对正数排序且保持负数原位置不变?

问题背景

需求为修改归并排序算法,实现仅对数组内正数元素排序、所有负数元素保留在原始位置不移动的效果。
原有标准归并排序会全量排序所有元素,直接在合并逻辑中添加“仅元素大于0时执行替换”的判断会出现异常:要么负数发生位移,要么正数排序错乱。测试输入为[57, 16, -70, -66, -59, -18, 43, -26, -99, 41],错误修改后的输出为[57, 43, -70, 41, 43, 57, 16, -70, 16, 57],期望输出为[16, 41, -70, -66, -59, -18, 43, -26, -99, 57]。
原有归并排序实现代码:

def merge_sort(arr):
    if len(arr) > 1: 
        mid = len(arr)//2 
        left = arr[:mid] 
        right = arr[mid:]
        merge_sort(left) 
        merge_sort(right) 
        i = j = k = 0
        while i < len(left) and j < len(right): 
            if left[i] < right[j]:
                arr[k] = left[i]  
                i+=1 
            else:
                arr[k] = right[j] 
                j+=1 
            k+=1 
        while i < len(left):
            arr[k] = left[i] 
            i+=1
            k+=1
        while j < len(right): 
            arr[k] = right[j] 
            j+=1
            k+=1
错误原因

直接在合并判断中添加正数校验的方案存在本质逻辑缺陷:

  • 归并拆分阶段的左右子数组全量包含正、负数,没有区分需要固定位置的负数和需要排序的正数
  • 合并阶段的k指针按数组全长度逐位移动,遇到负数时如果跳过赋值,会导致后续元素覆盖错位、指针不同步,最终出现元素重复、顺序错乱的问题
正确实现方案

不需要改动原有归并排序的核心逻辑,只需要增加一层位置处理逻辑,全程不触碰负数的存储位置:

  1. 遍历原数组,记录所有正数的索引位置和对应值
  2. 用原有归并排序对提取出的纯正数列表做排序
  3. 将排好序的正数按顺序填回之前记录的原正数索引位置,负数全程不做任何修改
    完整可运行代码:
def merge_sort(arr):
    if len(arr) > 1: 
        mid = len(arr)//2 
        left = arr[:mid] 
        right = arr[mid:]
        merge_sort(left) 
        merge_sort(right) 
        i = j = k = 0
        while i < len(left) and j < len(right): 
            if left[i] < right[j]:
                arr[k] = left[i]  
                i+=1 
            else:
                arr[k] = right[j] 
                j+=1 
            k+=1 
        while i < len(left):
            arr[k] = left[i] 
            i+=1
            k+=1
        while j < len(right): 
            arr[k] = right[j] 
            j+=1
            k+=1
    return arr

def sort_positive_keep_negative(arr):
    # 提取正数的位置和值
    pos_indexes = []
    pos_values = []
    for idx, num in enumerate(arr):
        if num > 0:
            pos_indexes.append(idx)
            pos_values.append(num)
    # 归并排序正数列表
    sorted_pos = merge_sort(pos_values)
    # 回填正数到原位置
    for idx, val in zip(pos_indexes, sorted_pos):
        arr[idx] = val
    return arr

# 测试验证
if __name__ == "__main__":
    test_arr = [57, 16, -70, -66, -59, -18, 43, -26, -99, 41]
    print(sort_positive_keep_negative(test_arr))
    # 输出:[16, 41, -70, -66, -59, -18, 43, -26, -99, 57],完全匹配期望结果

如果强行在归并递归拆分、合并流程中直接实现该效果,需要在每一层拆分、合并时全程跟踪负数位置,合并时遇到负数位置直接保留原值、移动指针不做比较赋值,逻辑复杂度高且容易出边界问题,远不如上述方案稳定易维护。

内容的提问来源于stack exchange,提问作者Turchick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 23:03:30