您的位置:首页 > Web前端

《剑指offer》-数组中的逆序对

2016-06-14 09:27 351 查看


题目描述

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数

解法:最容易想到的就是冒泡排序,第一个挨个和后面的去比较,统计次数,这种方法时间复杂度太高,所以采用归并排序的思想

          1.先递归分解数组,分为最小的单个

          2.合并的时候进行排序和统计逆序的个数

          3.主要是掌握归并排序的思想,这里需要用到一个辅助数组,用来存取合并后的数组,并递归地使用该数组作为输入

class Solution {
public:
     int InverseP(vector<int> &data, int start, int end, vector<int> &store) { //辅助数组需要引用传递,因为需要改变值
         if(start == end) {
             store[start] = data[start];
             return 0;
         }
        
        int length = (end - start) / 2;
        int left = InverseP(data, start, start + length, store);  //左边递归,这里递归需要注意,传递的数组是上一次合并的数组
        int right = InverseP(data, start + length + 1, end, store);  //右边递归
        //开始合并
        
        int i = start + length; //i指向左边数组,最后一个值
        int j = end;  //j指向右边数组,最后一个值
        int CopyIndex = end;
        int count = 0;
        while(i >= start && j >= start + length + 1) {
            if(data[i] > data[j]) {
                store[CopyIndex--] = data[i--];
                count += j - start - length; //注意这里的length是长度,不是中间mid的下标值,j-mid即可  mid=(start+end)/2     
            }
            else {
                store[CopyIndex--] = data[j--];
            }        
        }
        while(i >= start) store[CopyIndex--] = data[i--];
        while(j >= start + length + 1) store[CopyIndex--] = data[j--];
        for(int v = start; v <= end; v++)//这里store从end开始存,一直存到start为止,所以区别于归并排序里的从0开始存到结束为止
            data[v] = store[v];  //这步可以直接改写成在调用函数时,两边值互换的形式:InverseP(store, start, start + length, data);
        return left + right + count;
    }
    int InversePairs(vector<int> data) {
        int len = data.size();
        if(len == 0) return 0;
        int count = 0;
        vector<int> store;
        for(int i = 0; i < len; i++)
            store.push_back(data[i]);
        count = InverseP(data, 0, len - 1, store);
        return count;
    }
   
};

便于对比,下面给出归并排序的代码:

#include <stdio.h>
#include "string.h"
#include "iostream"
using namespace std;
void merge(int* unsorted, int first, int mid, int last, int* sorted)
{
int i = first, j = mid;
int k = 0;
while (i < mid && j < last) {
if (unsorted[i] < unsorted[j])
sorted[k++] = unsorted[i++];
else
sorted[k++] = unsorted[j++];
}

while (i < mid)
sorted[k++] = unsorted[i++];
while (j < last)
sorted[k++] = unsorted[j++];

for (int v = 0; v < k; v++)
unsorted[first+v] = sorted[v];
}

void merge_sort(int* unsorted, int first, int last, int* sorted)
{
if (first + 1 < last)
{
int mid = (first + last) / 2;
//Console.WriteLine("{0}-{1}-{2}", first, mid, last);
merge_sort(unsorted, first, mid, sorted);
merge_sort(unsorted, mid, last, sorted);
merge(unsorted, first, mid, last, sorted);
}
}

int main()
{
int x[6] = { 6, 2, 4, 1, 5, 9 };
int *sorted = new int[6];
merge_sort(x, 0, 6, sorted);
for (int i = 0; i < 6; i++)
{
if (x[i] > 0)
cout<<x[i];
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: