使用归并排序计算无序数列转换为升序的最少交换次数
为了计算将一个无序数列通过交换相邻元素转换为升序数列所需的最少交换次数,可以使用归并排序算法。在归并排序的合并过程中,当需要将右边的元素插入到左边时,就可以统计出逆序对的数量,而逆序对的数量就是将数列通过交换相邻元素转换为升序所需的最少交换次数。 以下是使用Python实现的代码: ```python # 归并排序并统计逆序对数量的函数 def merge_sort_and_count(arr): # 如果数组长度小于等于1,直接返回数组和逆序对数量0 if len(arr) <= 1: return arr, 0 # 找到数组的中间位置 mid = len(arr) // 2 # 递归对左半部分数组进行归并排序并统计逆序对 left, inv_left = merge_sort_and_count(arr[:mid]) # 递归对右半部分数组进行归并排序并统计逆序对 right, inv_right = merge_sort_and_count(arr[mid:]) # 合并左右两部分数组并统计逆序对 merged, inv_merge = merge_and_count(left, right) # 总的逆序对数量为左半部分、右半部分和合并过程中的逆序对数量之和 total_inversions = inv_left + inv_right + inv_merge return merged, total_inversions # 合并两个有序数组并统计逆序对数量的函数 def merge_and_count(left, right): # 初始化合并后的数组 merged = [] # 初始化逆序对数量为0 inversions = 0 # 初始化左右数组的索引 i, j = 0, 0 # 当左右数组都还有元素时 while i < len(left) and j < len(right): if left[i] <= right[j]: # 如果左数组当前元素小于等于右数组当前元素,将左数组元素加入合并后的数组 merged.append(left[i]) i += 1 else: # 如果左数组当前元素大于右数组当前元素,将右数组元素加入合并后的数组 merged.append(right[j]) j += 1 # 统计逆序对数量,左数组中剩余的元素都与当前右数组元素构成逆序对 inversions += len(left) - i # 将左数组剩余元素加入合并后的数组 merged.extend(left[i:]) # 将右数组剩余元素加入合并后的数组 merged.extend(right[j:]) return merged, inversions # 读取输入 n = int(input()) arr = list(map(int, input().split())) # 调用归并排序并统计逆序对数量的函数 _, inversions = merge_sort_and_count(arr) # 输出最少交换次数 print(inversions) ``` ### 代码解释: 1. **`merge_sort_and_count`函数**:该函数使用递归的方式对数组进行归并排序,同时统计逆序对的数量。它将数组分成左右两部分,分别对左右两部分进行递归排序并统计逆序对数量,然后合并左右两部分并统计合并过程中的逆序对数量,最后返回排序好的数组和总的逆序对数量。 2. **`merge_and_count`函数**:该函数用于合并两个有序数组,并统计合并过程中的逆序对数量。在合并过程中,如果左数组的当前元素大于右数组的当前元素,那么左数组中剩余的所有元素都与右数组的当前元素构成逆序对,将逆序对数量累加到`inversions`中。 3. **主程序**:读取输入的数组长度和数组元素,调用`merge_sort_and_count`函数进行排序并统计逆序对数量,最后输出最少交换次数。 ######[AI问答 | 880点数解答 | 2026-03-17 17:46:26]
- C++ 实现旋律类型判断:根据 7 个音符顺序输出升序、降序或混合(字节豆包 | 582点数解答 | 2026-03-21 19:41:16)23
- C++实现二进制转八进制及旋律类型判断(字节豆包 | 629点数解答 | 2026-03-21 19:50:41)31
- JSP 实现商品展示模块:分页、搜索、交互与美观界面全搞定!(字节豆包 | 19点数解答 | 2024-12-13 15:00:43)363
- C++ 实现:轻松找出 n 个整数中的第二小值(字节豆包 | 260点数解答 | 2026-02-07 21:19:29)42
- C++实现找出数组中第二小的值(字节豆包 | 526点数解答 | 2026-03-27 19:40:26)22
- 找出数组中第二小值的C++代码实现(字节豆包 | 696点数解答 | 2026-03-28 19:40:41)21
- C++实现数组特定位置最小值交换并输出指定元素(字节豆包 | 607点数解答 | 2026-04-04 19:31:04)21
- C++实现找出n个整数中第二小的值(字节豆包 | 361点数解答 | 2026-04-06 20:52:02)25
- 巧用 Python 求解数列积之和,附输入输出及样例详解!(字节豆包 | 263点数解答 | 2026-01-24 13:02:54)53
- PyCharm 中用 Selenium 编写自动化测试脚本,轻松登录 eShop 测试平台并点击“我的订单”(字节豆包 | 304点数解答 | 2024-11-06 15:38:30)458
- C++ 代码实现自定义运算 x@y = x² + y² - xy 及 x@(x+y) 计算(DeepSeek | 215点数解答 | 2025-12-13 15:08:14)98
- C++ 实现根据输入正整数奇偶性计算偶数和或约数和(字节豆包 | 838点数解答 | 2026-02-28 20:23:59)56