博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
逆序数相关题
阅读量:7025 次
发布时间:2019-06-28

本文共 2817 字,大约阅读时间需要 9 分钟。

    逆序数的题最经典的就是求逆序对数,可以直接冒泡然后记录交换的次数,时间复杂度O(n^2)。也可以用修改版的归并排序来做,时间复杂度会降到O(nlogn)。然后,有一种题是有一队人,每个人都知道自己的身高和前面比自己高的人数,队伍解散后怎么才能恢复队伍?这个题给的信息实际上就是逆序对数,根据逆序对数恢复元素位置,我想到的办法是用类似于插入排序的东西来做。下面有实现代码,现根据身高求出每个人前面比自己高的人数(逆序对数),然后用洗牌算法打乱队伍,最后恢复队伍。

#include 
#include 
#include 
#include 
 
using namespace std;
 
struct person
{
int id;
float height;
int higher_in_front;
};
 
// Use merge sort algorithm to calculate the higher person in front.
void calc_higher_in_front(person *begin, person *end, person *scratch)
{
if (begin == NULL || end == NULL || scratch == NULL)
{
return;
}
 
if (begin == end || begin + 1 == end)
{
return;
}
 
person *mid = begin + (end - begin) / 2;
 
calc_higher_in_front(begin, mid, scratch);
calc_higher_in_front(mid, end, scratch);
 
person *left = begin;
person *right = mid;
person *result = scratch;
 
while (left != mid || right != end)
{
if (left < mid && (right == end || left->height < right->height))
{
*result++ = *left++;
}
else
{
right->higher_in_front += (mid - left);
 
*result++ = *right++;
}
}
 
memcpy(begin, scratch, sizeof(person) * (end - begin));
}
 
// Shuffle algorithm
void shuffle(person *begin, person *end)
{
if (begin == NULL || end == NULL)
{
return;
}
 
if (begin == end || begin + 1 == end)
{
return;
}
 
size_t len = end - begin;
 
srand((unsigned)time(0));
 
for (size_t i = 0; i < len; ++i)
{
// Assume (rand() % (len - i)) + i produce random number
// between i and len - 1 equal probability.
swap(begin[i], begin[(rand() % (len - i)) + i]);
}
}
 
// Rebuild original sequence of person.
void rebuild(person *begin, person *end)
{
struct comp_by_higher_in_front
{
bool operator()(const person &lhs, const person &rhs) const
{
if (lhs.higher_in_front != rhs.higher_in_front)
{
return lhs.higher_in_front < rhs.higher_in_front;
}
else
{
return lhs.height < rhs.height;
}
}
};
 
sort(begin, end, comp_by_higher_in_front());
 
person *curr = begin;
 
while (curr != end)
{
if (curr->higher_in_front != 0)
{
break;
}
 
++curr;
}
 
for (; curr != end; ++curr)
{
person *p = begin, key = *curr;
int higher_count = 0;
 
while (p != curr)
{
if (p->height > key.height)
{
++higher_count;
 
if (higher_count > key.higher_in_front)
{
break;
}
}
 
++p;
}
 
if (p != curr)
{
memmove(p + 1, p, (curr - p) * sizeof(person));
*p = key;
}
}
}
 
int main(int argc, char **argv)
{
person p[10];
 
memset(p, 0, sizeof(p));
 
for (int i = 0; i < 10; ++i)
{
p[i].id = i + 1;
}
 
p[0].height = 1.76f;
p[1].height = 1.6f;
p[2].height = 1.7f;
p[3].height = 1.8f;
p[4].height = 1.75f;
p[5].height = 1.5f;
p[6].height = 1.56f;
p[7].height = 1.61f;
p[8].height = 1.55f;
p[9].height = 1.71f;
 
person *scratch = new person[10];
 
calc_higher_in_front(p, p + 10, scratch);
shuffle(p, p + 10);
rebuild(p, p + 10);
 
// After rebuild, the p array should be restored.
 
return 0;
}

转载地址:http://tdsxl.baihongyu.com/

你可能感兴趣的文章
星号密码探测工具 - 代码远程线程注入的简单运用
查看>>
时间字符串的转换
查看>>
android sqlite
查看>>
Codeforces Beta Round #18 (Div. 2 Only) C. Stripe 前缀和
查看>>
【ALearning】第二章 Androidproject知识介绍
查看>>
SharePoint 2013 在母版页中插入WebPart
查看>>
CentOs6.5中安装和配置vsftp简明教程
查看>>
eclipse不自动弹出提示(Alt+/ 快捷键失效)
查看>>
JAVA实现AES的加密和解密算法
查看>>
【转】java 自动装箱与拆箱
查看>>
JAVA NIO异步通信框架MINA选型和使用的几个细节(概述入门,UDP, 心跳)
查看>>
【转】android自动化测试之MonkeyRunner使用实例(三)
查看>>
WebService它CXF注释错误(两)
查看>>
ThinkPad E431/E531 ubuntu 14.04 安装无线网卡驱动
查看>>
ABP理论学习之审计日志
查看>>
makefile 学习一
查看>>
jQuery中的Sizzle引擎分析
查看>>
yii 验证码 CCaptcha的总结(转)
查看>>
我的编程之路(二十五) 上海的老同学
查看>>
oracle汉字占用字节长度
查看>>