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

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

相关文章

Java面试题:通过实例说明内连接、左外连接和右外连接的区别

在 SQL 中,连接(JOIN)用于在多个表之间组合行。最常用的连接类型是内连接(INNER JOIN)、左外连接(LEFT OUTER JOIN)和右外连接(RIGHT OUTER JOIN)。它们的主要区别在于它们如何处理表之间的匹配和不匹配行。下面是每种连接的详细说明和示例。 表示例 假设有两个表:Customers 和 Orders。 Customers CustomerIDCus

一道经典Python程序样例带你飞速掌握Python的字典和列表

Python中的列表(list)和字典(dict)是两种常用的数据结构,它们在数据组织和存储方面有很大的不同。 列表(List) 列表是Python中的一种有序集合,可以随时添加和删除其中的元素。列表中的元素可以是任何数据类型,包括数字、字符串、其他列表等。列表使用方括号[]表示,元素之间用逗号,分隔。 定义和使用 # 定义一个列表 fruits = ['apple', 'banana

数据结构9——排序

一、冒泡排序 冒泡排序(Bubble Sort),顾名思义,就是指越小的元素会经由交换慢慢“浮”到数列的顶端。 算法原理 从左到右,依次比较相邻的元素大小,更大的元素交换到右边;从第一组相邻元素比较到最后一组相邻元素,这一步结束最后一个元素必然是参与比较的元素中最大的元素;按照大的居右原则,重新从左到后比较,前一轮中得到的最后一个元素不参4与比较,得出新一轮的最大元素;按照上述规则,每一轮结

七种排序方式总结

/*2018.01.23*A:YUAN*T:其中排序算法:冒泡排序,简单排序,直接插入排序,希尔排序,堆排序,归并排序,快速排序*/#include <stdio.h>#include <math.h>#include <malloc.h>#define MAXSIZE 10000#define FALSE 0#define TRUE 1typedef struct {i

【SparkStreaming】面试题

Spark Streaming 是 Apache Spark 提供的一个扩展模块,用于处理实时数据流。它使得可以使用 Spark 强大的批处理能力来处理连续的实时数据流。Spark Streaming 提供了高级别的抽象,如 DStream(Discretized Stream),它代表了连续的数据流,并且可以通过应用在其上的高阶操作来进行处理,类似于对静态数据集的操作(如 map、reduce、

拓扑排序——C语言

拓扑排序(Topological Sorting)是一种用于有向无环图(DAG)的排序算法,其输出是图中所有顶点的线性排序,使得对于每条有向边 (u, v),顶点 u 在 v 之前出现。拓扑排序确定了项目网络图中的起始事件和终止事件,也就是顶点的执行顺序。         因为是有向无环图,所以拓扑排序的作用其实就是把先发生的排序在前面,后发生的排序到后面。 例如现在我们有一个

六西格玛培训公司:解锁成功之门,让企业与个人共赴“嗨”途

在竞争激烈的21世纪,六西格玛培训公司手握一把神奇的钥匙,帮助企业及个人轻松开启成功的大门。 对企业来说: 产品质量飞跃:不再是偶尔的精品,而是每个产品都如同精雕细琢的艺术品,吸引无数顾客争相购买。 工作流程优化:六西格玛培训如同精准的剪刀,剪去冗余,让工作流程更加顺畅高效。 客户满意度飙升:深谙客户需求的六西格玛,帮助企业精准把握市场脉搏,让每位客户都感受到宾至如归的满意。 战略转型游刃有

IPD推行成功的核心要素(十一)技术规划与平台规划促进公司战略成功

随着外部大环境的影响,各企业仅有良好的愿望是不够的。预测并顺应新兴市场和技术的变化,变危机为转机,不断推出强大的产品才是一个公司持续繁荣的根本保障。而高效的产品开发往往是基于某些关键技术,针对市场推出的一个或几个产品系列,这些产品系列通常共用一些产品平台,共用一种或者几种关键技术。当一家企业进入了平稳发展期,已经建立了较为完善的管理制度和产品开发流程,但是依然认为竞争对手是那样强大,那样不可战胜。

Java线程面试题(50)

不管你是新程序员还是老手,你一定在面试中遇到过有关线程的问题。Java语言一个重要的特点就是内置了对并发的支持,让Java大受企业和程序员的欢迎。大多数待遇丰厚的Java开发职位都要求开发者精通多线程技术并且有丰富的Java程序开发、调试、优化经验,所以线程相关的问题在面试中经常会被提到。 在典型的Java面试中, 面试官会从线程的基本概念问起, 如:为什么你需要使用线程,

嵌入式学习——数据结构(哈希、排序)——day50

1. 查找二叉树、搜索二叉树、平衡二叉树 2. 哈希表——人的身份证——哈希函数 3. 哈希冲突、哈希矛盾 4. 哈希代码 4.1 创建哈希表 4.2  5. 算法设计 5.1 正确性 5.2 可读性(高内聚、低耦合) 5.3 健壮性 5.4 高效率(时间复杂度)时间复杂度越低,效率越高, 5.5 低储存(空间复杂度)空间复杂度越低,存储空间越少 6.排序算法 6.1 冒