面试题--本公司现在要给公司员工发波福利,在员工工作时间会提供大量的水果供员工补充营养。由于水果种类比较多,但是却又不知道哪种水果比较受欢迎,然后公司就让每个员工报告了自己最爱吃的k种水果

本文主要是介绍面试题--本公司现在要给公司员工发波福利,在员工工作时间会提供大量的水果供员工补充营养。由于水果种类比较多,但是却又不知道哪种水果比较受欢迎,然后公司就让每个员工报告了自己最爱吃的k种水果,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本公司现在要给公司员工发波福利,在员工工作时间会提供大量的水果供员工补充营养。由于水果种类比较多,但是却又不知道哪种水果比较受欢迎,然后公司就让每个员工报告了自己最爱吃的k种水果,并且告知已经将所有员工喜欢吃的水果存储于一个数组中。然后让我们统计出所有水果出现的次数,并且求出大家最喜欢吃的前k种水果。

void GetFavoriteFruit(const vector& fruits,size_t k);

思路一:
排序,但是我们又不知道有多少种水果,如果水果很多。排序将会带来很大的时间复杂度和空间复杂度。

那么,这道题应该怎么做呢?
当然,首选的应该是红黑树了,并且需要的是K/V结构的红黑树,K来存储水果的名称,V来存储这个水果出现的次数。
可是红黑树结构复杂,在面试的时候想写出来不是那么容易,所以这里有了STL两个容器,map和set。
set和map这两个容器的底层都是用红黑树来实现的,并且他们都具有防冗余的特性(被插入的数据如果在容器中已经出现,那么插入失败),他两的唯一区别就是set是一个K结构,而map是一个K/V结构。

map原型:

template < class Key,                                     class T,                                         class Compare = less<Key>,                     class Alloc = allocator<pair<const Key,T> >    > class map;  

Key:这个就是我刚才说的K/V结构中的K
T:这是K/V结构中的V。
Compare:这是一个接受仿函数类型的参数,可以控制map是一个升序的还是降续的(不传这个参数时,默认是升序)。
Alloc:空间配置器。

那么这个题该怎么解决?
定义一个map,然后将数组中所有的元素插入到map中,在插入前先使用find()来查找存在不存在,如果不存在则插入,如果存在,则利用find返回值来对找到的元素的V进行+1操作。(其中fruits是水果数组)

map<string, int> fruitCount;//创建map对象  
for (int i = 0; i < sizeof(fruits) / sizeof(fruits[0]); ++i)  
{  map<string, int>::iterator it = fruitCount.find(fruits[i]);//创建map迭代器  if (it != fruitCount.end())//先查找看该字符数组内是否存在该字符串  {  it->second++;//给该类对象的计数+1   }  else  {  fruitCount.insert(pair<string, int>(fruits[i], 1));  }  
}  

缺点:如果map中没有要插入的这个水果,则需要遍历两次map。

思路二:只遍历一次map
insert的返回值pair。既然不管是否插入成功,它都能返回我们需要的这个元素的迭代器。那么,我们可以先插入,然后对其返回值进行保存,如果该返回值得第二个参数是true,表示插入成功,不进行其他操作,如果为flase,表示插入失败,那么其返回的第一个参数将会带回已经存在的这个被插入元素的迭代器,当然轻而易举就可以通过迭代器拿到这个元素的第二个参数V。

void CalculateFruitCount(map<string,int>& m, string fruits[], size_t size)  
{  for (size_t i = 0; i < size; i++)  {  //m[fruits[i]]++;    //map中有operator[]的重载,其内容等同于下边代码  pair<map<string, int>::iterator, bool> ret;  ret = m.insert(make_pair(fruits[i], 1));  if (ret.second == false)  ret.first->second++;  }  
}  

现在走到这里已经全部插入了,那接下来我们就需要找前K个最喜欢的水果了。

思路一:
将统计好的数据全部放入一个vector中,并且利用排序算法sort进行排序。而其默认为升序,最大的则位于数组后边,但是我们并不知道vector有多大。所以,我们采用降续,这样最大的永远在vector的前列.

void GetBeginOfThreeFruits(map<string, int>& m, vector<map<string, int>::iterator>& v)  //按照水果出现的次数降续存储于v中  
{  map<string, int>::iterator it = m.begin();  while (it != m.end())  {  v.push_back(it);  it++;  }  struct Compare   //仿函数(降续)  {  bool operator()(map<string, int>::iterator l, map<string, int>::iterator r)  {  return l->second > r->second;  }  };  sort(v.begin(), v.end(),Compare());  
}  

思路二:给一个堆,这个堆只要K个大小。
因为找出现次数最多的,所以这里给一个小堆。堆顶元素为最小的数。每一次新进来的数字和堆顶比较,如果比堆顶小则不要。比堆顶大则把堆顶pop,把这个元素插入再重新排堆。

void GetBeginOfNFruits(map<string, int>& m, size_t n, vector<map<string,int>::iterator>& v)  
{  map<string, int> ::iterator it = m.begin();  for (size_t i = 0; i < n; ++i)  {  v.push_back(it);  it++;  }  struct Compare  //堆算法默认是大堆,此处需要仿函数将其改为小堆  {  bool operator()(map<string, int>::iterator l, map<string, int>::iterator r)  {  return l->second > r->second;  //小堆  }  };  make_heap(v.begin(), v.end(), Compare());  while (it != m.end())  {  if (it->second > v.front()->second)  {  pop_heap(v.begin(), v.end(), Compare());  v.pop_back();  v.push_back(it);  push_heap(v.begin(), v.end(), Compare());  }  it++;  }  
}  

这篇关于面试题--本公司现在要给公司员工发波福利,在员工工作时间会提供大量的水果供员工补充营养。由于水果种类比较多,但是却又不知道哪种水果比较受欢迎,然后公司就让每个员工报告了自己最爱吃的k种水果的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Python将大量遥感数据的值缩放指定倍数的方法(推荐)

《Python将大量遥感数据的值缩放指定倍数的方法(推荐)》本文介绍基于Python中的gdal模块,批量读取大量多波段遥感影像文件,分别对各波段数据加以数值处理,并将所得处理后数据保存为新的遥感影像... 本文介绍基于python中的gdal模块,批量读取大量多波段遥感影像文件,分别对各波段数据加以数值处

Python 标准库time时间的访问和转换问题小结

《Python标准库time时间的访问和转换问题小结》time模块为Python提供了处理时间和日期的多种功能,适用于多种与时间相关的场景,包括获取当前时间、格式化时间、暂停程序执行、计算程序运行时... 目录模块介绍使用场景主要类主要函数 - time()- sleep()- localtime()- g

SSID究竟是什么? WiFi网络名称及工作方式解析

《SSID究竟是什么?WiFi网络名称及工作方式解析》SID可以看作是无线网络的名称,类似于有线网络中的网络名称或者路由器的名称,在无线网络中,设备通过SSID来识别和连接到特定的无线网络... 当提到 Wi-Fi 网络时,就避不开「SSID」这个术语。简单来说,SSID 就是 Wi-Fi 网络的名称。比如

如何用Java结合经纬度位置计算目标点的日出日落时间详解

《如何用Java结合经纬度位置计算目标点的日出日落时间详解》这篇文章主详细讲解了如何基于目标点的经纬度计算日出日落时间,提供了在线API和Java库两种计算方法,并通过实际案例展示了其应用,需要的朋友... 目录前言一、应用示例1、天安门升旗时间2、湖南省日出日落信息二、Java日出日落计算1、在线API2

如何使用 Bash 脚本中的time命令来统计命令执行时间(中英双语)

《如何使用Bash脚本中的time命令来统计命令执行时间(中英双语)》本文介绍了如何在Bash脚本中使用`time`命令来测量命令执行时间,包括`real`、`user`和`sys`三个时间指标,... 使用 Bash 脚本中的 time 命令来统计命令执行时间在日常的开发和运维过程中,性能监控和优化是不

python中的与时间相关的模块应用场景分析

《python中的与时间相关的模块应用场景分析》本文介绍了Python中与时间相关的几个重要模块:`time`、`datetime`、`calendar`、`timeit`、`pytz`和`dateu... 目录1. time 模块2. datetime 模块3. calendar 模块4. timeit

Java将时间戳转换为Date对象的方法小结

《Java将时间戳转换为Date对象的方法小结》在Java编程中,处理日期和时间是一个常见需求,特别是在处理网络通信或者数据库操作时,本文主要为大家整理了Java中将时间戳转换为Date对象的方法... 目录1. 理解时间戳2. Date 类的构造函数3. 转换示例4. 处理可能的异常5. 考虑时区问题6.

百度/小米/滴滴/京东,中台架构比较

小米中台建设实践 01 小米的三大中台建设:业务+数据+技术 业务中台--从业务说起 在中台建设中,需要规范化的服务接口、一致整合化的数据、容器化的技术组件以及弹性的基础设施。并结合业务情况,判定是否真的需要中台。 小米参考了业界优秀的案例包括移动中台、数据中台、业务中台、技术中台等,再结合其业务发展历程及业务现状,整理了中台架构的核心方法论,一是企业如何共享服务,二是如何为业务提供便利。

服务器集群同步时间手记

1.时间服务器配置(必须root用户) (1)检查ntp是否安装 [root@node1 桌面]# rpm -qa|grep ntpntp-4.2.6p5-10.el6.centos.x86_64fontpackages-filesystem-1.41-1.1.el6.noarchntpdate-4.2.6p5-10.el6.centos.x86_64 (2)修改ntp配置文件 [r

【专题】2024飞行汽车技术全景报告合集PDF分享(附原数据表)

原文链接: https://tecdat.cn/?p=37628 6月16日,小鹏汇天旅航者X2在北京大兴国际机场临空经济区完成首飞,这也是小鹏汇天的产品在京津冀地区进行的首次飞行。小鹏汇天方面还表示,公司准备量产,并计划今年四季度开启预售小鹏汇天分体式飞行汽车,探索分体式飞行汽车城际通勤。阅读原文,获取专题报告合集全文,解锁文末271份飞行汽车相关行业研究报告。 据悉,业内人士对飞行汽车行业