某公司一道面试题:赛车名次, 桶排序

2024-05-28 09:38

本文主要是介绍某公司一道面试题:赛车名次, 桶排序,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目:

Suppose you are a fan of auto-racing and want to figure out which drivers are likely to perform well in an
upcoming race. Luckily you have access to a log of the times that each racer started and finished their test race
the day before.

The particular rating algorithm you have chosen is to assign each racer R a score that equals the number of
other racers who both started after R started and also finished before R finished.

Note that a lower score generally suggests that the racer is faster, and this rating algorithm keeps from penalizing
fast racers who have slow times simply because they are stuck behind a crash or slow racer. Additionally, this
rating algorithm does not reward fast racers who pass tons of slow racers in comparison to fast racers who race
when there are not many slow racers on the track to pass (compare this with rating a racer based on the net
number of passes).

More formally, you want to write a program that will read the test race log from standard input. The first line of
the log contains a single integer n from 0 to 70,000 that represents the number of racers in the log. The next n
lines of the test race log have the following format:
racerId startTime endTime
where racerId is an integer in the range [0,10^9] and startTime and endTime are both integers such that 0
<= startTime < endTime <= 10^18. Each racerId will be distinct. Also, the collection of all start and end
times will not contain any duplicate elements.

Given such an input, you should print output in the following format:
racerId score
where score is the score as defined above for racer racerId. The output lines should be sorted in ascending
order of score with ties broken by sorting by racerId, also in ascending order. This can be accomplished with
a simple sort at the end.

Directions:
Please code this problem in Java, C, or C++. Your solution should run in o(N^2) time on all inputs (i.e., strictly less
than O(N^2) -- an O(N^2) algorithm will not be fast enough).

Hint: The naive brute force solution is too slow to run within the time limit. You will need to think of a faster
solution. Specifically, we are looking for a solution that is guaranteed to be less than O(N^2) on all inputs. One
possible way to accomplish this (there are several other acceptable methods) is to use a data structure with K
buckets (e.g., K = 300), each of which is initially empty and is defined by two times. Each bucket will eventually
contain racers whose start time falls between the two times. The bucket boundaries should be chosen such that
they ultimately will contain the same number of racers. Then iterate through the racers in end time order and, as
you iterate over each racer, build up this bucketed data structure in such a way that you can use it to quickly
count the number of racers that finished before him but started after him.

What We Are Looking For:
For this problem, we simply want to see that you can implement the algorithm correctly, without particular regard
to principles of object orientation or modularity. Do give us at least minimal documentation to help us
understand what you are trying to accomplish in certain key places of the algorithm.

Example:
input:
5
2 100 200
3 110 190
4 105 145
1 90 150
5 102 198

output:
3 0
4 0
1 1
5 2
2 3

Note in the above example that racer 3 has a score of 0 because no one starts after racer 3 (a drawback to this
scoring system is the last racer always has a score of 0). Racer 4 also has a score of 0 because the only racer who
starts after racer 4's start time (racer 3) has a later finish time. Racer 3 is listed ahead of racer 4 despite having a
slower time because racer 3's id is lower. At the other end, racer 2 has a score of 3 because racers 3, 4, and 5
start after racer 2 and finish before racer 2 finishes.

解答:

要注意的几点:

1)输入是stdin;

2)赛车手编号范围0-10^9,int;开始和完成时间0-10^18,long long;

3)桶排序,桶的尺寸和个数。


#include <iostream>
#include <vector>
#include <cassert>
#include <set>using namespace std;typedef int racerID_t;
typedef long long startTime_t;
typedef long long endTime_t;struct racer {racerID_t racerID;startTime_t startTime;endTime_t endTime;racer(racerID_t arg_racer, startTime_t arg_st, endTime_t arg_et):racerID(arg_racer), startTime(arg_st), endTime(arg_et) {} 
};struct endTimeSort{bool operator()(racer r1, racer r2){return r1.endTime > r2.endTime;}
};struct scoreSort{bool operator()(pair<racerID_t, int> r1, pair<racerID_t, int> r2){if(r1.second == r2.second)return r1.first < r2.first;else {return r1.second < r2.second;}}
};int main() {int numberOfRacer = 0;int bucketSize = 100;cin >> numberOfRacer;int numberOfBuckets = numberOfRacer / bucketSize;vector<racer> racerArray;/// Initialize the buckets.vector<set<racer, endTimeSort>> racerBucket(numberOfBuckets + 1);assert( numberOfRacer != 0 );startTime_t maxStartTime = 0;while( numberOfRacer > 0 ){racerID_t id;startTime_t start;endTime_t end;cin >> id >> start >> end;if( start > maxStartTime)maxStartTime = start;racerArray.push_back(racer(id, start, end));numberOfRacer--;}/// while( !racerArray.empty() ){racer current = racerArray.back();int bucketIndex = (int)((double)(current.startTime / maxStartTime) * numberOfBuckets);racerBucket[bucketIndex].insert(current);racerArray.pop_back();}set<pair<racerID_t, int>, scoreSort> scoreArray;for(vector<set<racer, endTimeSort>>::iterator iter = racerBucket.begin(); iter < racerBucket.end(); iter++){for(set<racer, endTimeSort>::iterator iter2 = iter->begin(); iter2 != iter->end(); iter2++){int score = 0;racerID_t id = iter2->racerID;for(set<racer, endTimeSort>::iterator iter3 = iter2; iter3 != iter->end(); iter3++){if(iter3->startTime >= iter2->startTime && iter3->endTime < iter2->endTime)score++;}scoreArray.insert(pair<racerID_t, int>(id, score));}}for(set<pair<racerID_t, int>, scoreSort>::iterator iter = scoreArray.begin(); iter != scoreArray.end(); iter++){cout << iter->first << " " << iter->second << endl;}return 0;
}

一年后修改做法:

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include <cmath>
#include<climits>using namespace std;typedef int racerID_t;
typedef long long startTime_t;
typedef long long endTime_t;struct Racer {racerID_t racerID;startTime_t startTime;endTime_t endTime;int score;
};struct Bucket {vector<startTime_t> startTimes;startTime_t earliestStartTime;startTime_t latestStartTime;
};bool startTimeSort(const Racer r1, const Racer r2) {return r1.startTime < r2.startTime;
}bool endTimeSort(const Racer r1, const Racer r2) {return r1.endTime < r2.endTime;
}bool scoreSort(const Racer r1, const Racer r2) {if(r1.score == r2.score)return r1.racerID < r2.racerID;elsereturn r1.score < r2.score;
}int getBucketIndex(vector<Bucket> & buckets, long long startTime) {int low = 0, high = (int)buckets.size()-1;int middle = 0;while(low <= high) {middle = (low + high) / 2;if(buckets[middle].earliestStartTime <= startTime && buckets[middle].latestStartTime >=  startTime)return middle;else if(buckets[middle].earliestStartTime > startTime)high = middle - 1;elselow = middle + 1;}return middle;
}int insertAndComputeScore(vector<Bucket> & buckets, int startBucket, int endBucket, long long startTime) {vector<long long>::iterator iter = buckets[startBucket].startTimes.begin();int temp = 0;for(; iter!= buckets[startBucket].startTimes.end(); iter++) {if(*iter > startTime) {buckets[startBucket].startTimes.insert(iter, startTime);break;}temp++;}if(iter == buckets[startBucket].startTimes.end())buckets[startBucket].startTimes.push_back(startTime);int score = (int)buckets[startBucket].startTimes.size() - temp - 1;for(int j = startBucket + 1; j <= endBucket; j++)score += buckets[j].startTimes.size();return score;
}void initBuckets(vector<Bucket> & buckets, vector<Racer> & racers) {int numberOfBuckets = (int)sqrt(racers.size());//cout << numberOfBuckets << endl;int racersPerBucket = (int)racers.size() / numberOfBuckets;sort(racers.begin(), racers.end(), startTimeSort);for(int i = 0; i < numberOfBuckets; i++) {buckets.push_back(Bucket());buckets[i].earliestStartTime = racers[i * racersPerBucket].startTime;buckets[i].latestStartTime = racers[i * racersPerBucket + racersPerBucket - 1].startTime;}buckets[numberOfBuckets-1].latestStartTime = LLONG_MAX;
}void fillBucket(vector<Bucket> & buckets, vector<Racer> & racers) {unsigned numberOfRacers = (unsigned)racers.size();sort(racers.begin(), racers.end(), endTimeSort);int whichBucketStart = 0, whichBucketEnd = 0;for(unsigned i = 0; i < numberOfRacers; i++) {whichBucketStart = getBucketIndex(buckets, racers[i].startTime);whichBucketEnd = getBucketIndex(buckets, racers[i].endTime);racers[i].score = insertAndComputeScore(buckets, whichBucketStart, whichBucketEnd, racers[i].startTime);}
}int main(int argc, const char * argv[])
{ifstream infile("data.txt", ios::in);if(infile) {vector<Racer> racers;string line;getline(infile, line);int number = atoi(line.c_str());for(int i = 0; i < number; i++) {Racer r;getline(infile, line);string word;istringstream stream(line);stream >> word;r.racerID = atoi(word.c_str());stream >> word;r.startTime = atoll(word.c_str());stream >> word;r.endTime = atoll(word.c_str());racers.push_back(r);}infile.close();vector<Bucket> buckets;initBuckets(buckets, racers);fillBucket(buckets, racers);sort(racers.begin(), racers.end(), scoreSort);//Test start.for(int i = 0; i < racers.size(); i++)cout << racers[i].racerID << " " << racers[i].score << endl;ofstream outfile("result.txt");if(outfile) {for(int i = 0; i < racers.size(); i++)outfile << racers[i].racerID << " " << racers[i].score << endl;outfile.close();} else {cout << "The file doesn't exist!" << endl;}//Test end.} else {cout << "The file does not exist." << endl;}return 0;
}


这篇关于某公司一道面试题:赛车名次, 桶排序的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1010205

相关文章

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

hdu 1285(拓扑排序)

题意: 给各个队间的胜负关系,让排名次,名词相同按从小到大排。 解析: 拓扑排序是应用于有向无回路图(Direct Acyclic Graph,简称DAG)上的一种排序方式,对一个有向无回路图进行拓扑排序后,所有的顶点形成一个序列,对所有边(u,v),满足u 在v 的前面。该序列说明了顶点表示的事件或状态发生的整体顺序。比较经典的是在工程活动上,某些工程完成后,另一些工程才能继续,此时

荣耀嵌入式面试题及参考答案

在项目中是否有使用过实时操作系统? 在我参与的项目中,有使用过实时操作系统。实时操作系统(RTOS)在对时间要求严格的应用场景中具有重要作用。我曾参与的一个工业自动化控制项目就采用了实时操作系统。在这个项目中,需要对多个传感器的数据进行实时采集和处理,并根据采集到的数据及时控制执行机构的动作。实时操作系统能够提供确定性的响应时间,确保关键任务在规定的时间内完成。 使用实时操作系统的

《数据结构(C语言版)第二版》第八章-排序(8.3-交换排序、8.4-选择排序)

8.3 交换排序 8.3.1 冒泡排序 【算法特点】 (1) 稳定排序。 (2) 可用于链式存储结构。 (3) 移动记录次数较多,算法平均时间性能比直接插入排序差。当初始记录无序,n较大时, 此算法不宜采用。 #include <stdio.h>#include <stdlib.h>#define MAXSIZE 26typedef int KeyType;typedef char In

一些其他面试题

阿里二面:那你来说说定时任务?单机、分布式、调度框架下的定时任务实现是怎么完成的?懵了。。_哔哩哔哩_bilibili 1.定时算法 累加,第二层每一个格子是第一层的总时间400 ms= 20 * 20ms 2.MQ消息丢失 阿里二面:高并发场景下引进消息队列有什么问题?如何保证消息只被消费一次?真是捏了一把汗。。_哔哩哔哩_bilibili 发送消息失败

【软考】希尔排序算法分析

目录 1. c代码2. 运行截图3. 运行解析 1. c代码 #include <stdio.h>#include <stdlib.h> void shellSort(int data[], int n){// 划分的数组,例如8个数则为[4, 2, 1]int *delta;int k;// i控制delta的轮次int i;// 临时变量,换值int temp;in

zookeeper相关面试题

zk的数据同步原理?zk的集群会出现脑裂的问题吗?zk的watch机制实现原理?zk是如何保证一致性的?zk的快速选举leader原理?zk的典型应用场景zk中一个客户端修改了数据之后,其他客户端能够马上获取到最新的数据吗?zk对事物的支持? 1. zk的数据同步原理? zk的数据同步过程中,通过以下三个参数来选择对应的数据同步方式 peerLastZxid:Learner服务器(Follo

java常用面试题-基础知识分享

什么是Java? Java是一种高级编程语言,旨在提供跨平台的解决方案。它是一种面向对象的语言,具有简单、结构化、可移植、可靠、安全等特点。 Java的主要特点是什么? Java的主要特点包括: 简单性:Java的语法相对简单,易于学习和使用。面向对象:Java是一种完全面向对象的语言,支持封装、继承和多态。跨平台性:Java的程序可以在不同的操作系统上运行,称为"Write once,

学习记录:js算法(二十八):删除排序链表中的重复元素、删除排序链表中的重复元素II

文章目录 删除排序链表中的重复元素我的思路解法一:循环解法二:递归 网上思路 删除排序链表中的重复元素 II我的思路网上思路 总结 删除排序链表中的重复元素 给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。 图一 图二 示例 1:(图一)输入:head = [1,1,2]输出:[1,2]示例 2:(图