《剑指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];
}
}
相关文章推荐
- jquery制作图标导航插件鼠标悬停放大显示特效代码
- [乐意黎]CSS属性探秘系列:vertical-align
- 介绍一种基于gulp对seajs的模块做合并压缩的方式
- 浅析jQuery 3.0中的Data
- js控件Kindeditor实现图片自动上传功能
- JavaScript中偶遇工厂模式
- js和循环依赖
- cordova + ionic 使用中碰到的一些问题
- javascript-第九节-键值或按钮控制div移动、轮播
- javascript-第八节-DOM对象实例集合
- HTML学习笔记--HTML的语法详解(必看)
- javascript-第七节-JS面向对象、其他定义类和对
- listview的多条目样式适配
- Minimum Depth of Binary Tree - Javascript
- JS设计模式之迭代器模式
- HTML学习笔记四
- jquery源码学习笔记二:jQuery工厂
- jQuery 3.0 的 Data 浅析
- jquery源码学习笔记二:jQuery工厂
- Path Sum