微软2010年笔试题
在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序数对。一个排列中逆序的总数就称为这个排列的逆序数。如{2,4,3,1}中,2和1,4和3,4和1,3和1是逆序数对,因此整个数组的逆序数对个数为4,现在给定一数组,要求统计出该数组的逆序数对个数。
这个题目是我在别人的csdn上看到的,没有想到微软也会出这样的题目,准确的是说在刘汝佳的算法入门经典中这是一道菜鸟题目,我记得我有一次比赛中还碰到这个题目了,那个时候直接把刘汝佳的代码copy一下,直接就AC了,之后那次比赛还每个人得了100¥,我用了两个小时就把100¥全部消耗殆尽,现在想一想我都不知道如何做的了,实在是可惜啊。
现在在把所有做过的题目都复习一下,以后怕问到,我知道题目,不知道如果做,现在越来越不如以前了,想一想以前刷题的日子,实在对自己失望。
首先是写出归并排序的代码由于本题要在归并排序之上改变一下,所以要借助归并排序。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
void Merge_sort (int *arr, int *temp, int x, int y) {
if (y - x > 1) {
int m = x + (y-x)/2;
int q = x, p = m;
int i = x;
Merge_sort (arr, temp, x, m);
Merge_sort (arr, temp, m, y);
while (q < m || p < y) {
if (p >= y || (q < m && arr[q] < arr[p])) temp[i++] = arr[q++];
else temp[i++] = arr[p++];
}
for (int i = x;i < y;i++) {
arr[i] = temp[i];
}
}
}
int main (void) {
int num;
int arr[100];
int temp[100];
while (scanf ("%d", &num) != EOF) {
for (int i = 0;i < num;i++){
scanf ("%d", &arr[i]);
}
Merge_sort (arr, temp, 0, num);
for (int i = 0;i < num;i++) {
printf ("%d ", arr[i]);
}
printf ("\n");
}
}
求逆序对数就是在上面的归并中改变一下就能求出了。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
int Cnt;
void Merge_sort (int *arr, int *temp, int x, int y) {
if (y - x > 1) {
int m = x + (y-x)/2;
int p = x,q = m;
int i = x;
Merge_sort (arr, temp, x, m);
Merge_sort (arr, temp, m, y);
while (q < m || p < y) {
if (p >= y || (q < m && arr[q] < arr[p])) temp[i++] = arr[q++];
else {temp[i++] = arr[p++]; Cnt += m-p;}
}
for (int i = x;i < y;i++) {
arr[i] = temp[i];
}
}
}
int main (void) {
int num;
int arr[100];
int temp[100];
while (scanf ("%d", &num) != EOF) {
for (int i = 0;i < num;i++) {
scanf ("%d", &arr[i]);
}
Cnt = 0;
Merge_sort (arr, temp, 0, num);
printf ("Cnt = %d", Cnt);
}
}