分治法与贪心法
(1)逆序对问题
设A[1,….n]是一个包含n个不同非负整数的数组。若果i<j的情况下,有A[i]>A[j],则(A[i],A[j])就称为A中的一个逆序对。请设计一个时间复杂度不超过O(n*lgn)的算法并编程实现,统计任意长度的数组A中全部逆序对的个数。
(2)最优合并问题
给定k个有序序列s1 , s2,... , sk , 用2路合并算法将这k个序列合并成一个序列。假设所采用的2路合并算法合并2个长度分别为m和n的序列需要m + n -1次比较。试设计一个算法确定合并这个序列的最优合并顺序,使所需的总比较次数最少(要求输出相应的合并顺序)。
上机12 逆序对问题
—、分治法
2、算法思想
可以使用分治法解决上面问题。具体如下:利用归并方法给序列排序,将n个元素划分为n 个子序列,相邻的两个子序列进行规并操作:
- 如果前一个子序列a1第一个元素大于后一个子序列a2第一个元素时,把a1的第一个元素放到归并序列中,同时把a1序列的第一个元素下标加1和归并子序列的最后一个元素下标加一。
- 如果前一个子序列a1第一个元素小于后一个子序列a2第一个元素时,把a2的第一个元素放到归并序列中,同时把a2序列的第一个元素下标加1和归并子序列的最后一个元素下标加1,还有的是通过a1的最后一个元素的下标减第一个元素的下标得出a1目前子序列的长度,用计数器(初始为0)记录该a1长度,并把每次的记录累加。
依次进行每一对子序列归并操作。操作完成后,把该归并后的新的子序列再进行归并操作,直到规模子序列数量只剩下1个。
- 实现代码及运行结果
程序源代码如下
#include <stdio.h>
#define LEN 100 //宏定义数组的大小
int tmp[LEN] = {};
int n;
int counter = 0;
void _mergeSort(int * array, int start, int middle, int end)
{
int i, j, k;
int second = middle + 1; //第二个子序列开始的下标
int first = start; //第一个子序列开始的下标
int index = start; //tmp数组开始的下标
while(first <= middle && second <= end)
{
if(array[first] <= array[second])
{
tmp[index] = array[first];
first++;
index++;