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

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

相关文章

Spring排序机制之接口与注解的使用方法

《Spring排序机制之接口与注解的使用方法》本文介绍了Spring中多种排序机制,包括Ordered接口、PriorityOrdered接口、@Order注解和@Priority注解,提供了详细示例... 目录一、Spring 排序的需求场景二、Spring 中的排序机制1、Ordered 接口2、Pri

大数据小内存排序问题如何巧妙解决

《大数据小内存排序问题如何巧妙解决》文章介绍了大数据小内存排序的三种方法:数据库排序、分治法和位图法,数据库排序简单但速度慢,对设备要求高;分治法高效但实现复杂;位图法可读性差,但存储空间受限... 目录三种方法:方法概要数据库排序(http://www.chinasem.cn对数据库设备要求较高)分治法(常

Python中lambda排序的六种方法

《Python中lambda排序的六种方法》本文主要介绍了Python中使用lambda函数进行排序的六种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们... 目录1.对单个变量进行排序2. 对多个变量进行排序3. 降序排列4. 单独降序1.对单个变量进行排序

关于Java内存访问重排序的研究

《关于Java内存访问重排序的研究》文章主要介绍了重排序现象及其在多线程编程中的影响,包括内存可见性问题和Java内存模型中对重排序的规则... 目录什么是重排序重排序图解重排序实验as-if-serial语义内存访问重排序与内存可见性内存访问重排序与Java内存模型重排序示意表内存屏障内存屏障示意表Int

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

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 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 发送消息失败