新鲜出炉,分享一道阿里的笔试题

简介: Hello,大家好,我是鸭血粉丝~最近朋友出去面试某大厂,收到一题笔试题,阿粉看了下还是挺有意思的,跟大家分享一下。首先我们先来看下题目的要求:现在一个文件,包含大量的 sku 数据, 我们需要针对这些数据,需要完成三道题目。这里就不完整介绍三道题目,今天就介绍前两道题目。

Hello,大家好,我是鸭血粉丝~

最近朋友出去面试某大厂,收到一题笔试题,阿粉看了下还是挺有意思的,跟大家分享一下。

首先我们先来看下题目的要求:

现在一个文件,包含大量的 sku 数据, 我们需要针对这些数据,需要完成三道题目。

这里就不完整介绍三道题目,今天就介绍前两道题目。

题目1:

我们需要实现一个方法,从包含 sku 的文件中读取数据,并且逐条打印。「注意:假设 sku 数据很多, 无法将 sku 列表完全加载到内存中」

题目 2:

现在需要统计 sku 数据,假设所有sku的价格都是精确到1元且一定小于1万元,计算当前这堆数据中,经过排序后的中间的价格。比如价格为1、1、2、25、25、25、25,按照题目要求,是第4个价格【25】)

「注意:假设 sku 数据很多, 无法将 sku 列表完全加载到内存中」

题目一

题目一其实非常简单,读取文件数据,遍历打印即可。

不过这里需要一点,题目再三强调了,sku 数据很多数据,无法加载到内存。

也就是说我们不能将数据全部读到内存中,然后遍历打印。

这就要求我们只能通过「流的方式」,逐条读取,然后打印输出。

流的方式,可以想到使用 BufferedReader 方式,一行一行读取。

不过,使用BufferedReader相关代码比较繁琐,由于当前笔试没要求 JDK 版本的,所以我们可以通过使用 JDK8  Files#lines 的流式读取的方式。

示例代码如下:

Files.lines(ResourceUtils.getFile("classpath:文件路径").toPath())
  // 跳过标题头
  .skip(1)
  // 遍历元素
  .forEach(line -> {
    // 将一行的字符串转化为一个对象,然后打印输出
  });

通过 Files#lines的方式,简化代码的复杂度,其实翻阅一下底层的源码,其实 Files#lines底层实际使用的是 BufferedReader

题目二

题目一其实比较简单,应该来说是个热身题。现在来说下题目二,难度就比较大了。

首先分析一下题目:

「现在需要统计 sku 数据,假设所有sku的价格都是精确到1元且一定小于1万元,计算当前这堆数据中,经过排序后的中间的价格。」

这道题目需要计算排在中间的价格,有的同学可能会想到,将 sku 数据全部读取一个数组中,然后按照价格做个排序,这处于数据中间不就是所需要的价格吗?

其实这么当然没问题,但是我们需要注意一个条件,题目给出的条件,「内存有限,无法加载全部的 sku 数到内存中」

这就直接破坏上述的方法。

那怎么办?

阿粉刚开始想的是,这个问题不就是海量数据求 「Top K」 ,然后搜索一下相关这类题解决办法,很复杂,那些解题思路编码起来也很复杂。

再次阅读了一下题目,阿粉看到关键信息:

「假设所有sku的价格都是精确到1元且一定小于1万元」

也就是说价格最多只有 1 万个元素,那我们是不是可以这样?

我们使用一个 TreeMap 保存数据,其中 key为价格,value为这个价格出现的次数。

由于 TreeMap自身就会按照 key 做排序,所以里面的数据天然有序。;

最后统计一下全部的数量,除以一半,自然就得到中间元素的位置。

然后遍历 TreeMap,计算中间元素的对应的价格。

// 价格为 key,value 为 sku 出现的次数
TreeMap<Integer, Integer> treeMap = new TreeMap<>();
// 使用题目一的方法遍历读取文件,将数据加载到  treeMap 中
Files.lines(ResourceUtils.getFile("classpath:文件路径").toPath())
  // 跳过标题头
  .skip(1)
  // 遍历元素
  .forEach(line -> {
    // 将一行的字符串转化为一个对象,然后打印输出
    // 由于价格都是整数
    // 这里使用 merge,如果当前这个价格在 map 中不存在,则值为 1,否则将调用后面的设置的函数
    treeMap.merge(skuDO.getPrice().intValue(), 1, Integer::sum);
  });
int mid = treeMap.size() / 2;
int midPrice = 0;
int count = 0;
for (Map.Entry<Integer, Integer> entry : treeMap.entrySet()) {
    // 第一次 count 大于等于 mid,代表中位数位于这个区间
    if (count + entry.getValue() >= mid) {
        // 中间的价格,偶数的情况下随便选一个
        midPrice = entry.getKey();
        break;
    }
  count += entry.getValue();
}
System.out.println("价格排序后在中间的价格为" + midPrice);

总结

这次笔试题,阿粉觉得设计还是挺好的,题目循序渐进,既考察了算法的思想,又可以看到面试人员的编码习惯,一箭双雕。

由于朋友是线下做的笔试题,所以题目相当充裕,也可以慢慢想,再不济还可以网上找找解题思路。

那如果你是在线笔试呢,如果碰到这类题目,没有思路怎么办?

那阿粉建议你跟面试官沟通一下,你可以讲下你对题目的理解,一些初步做法,然后也可以让其提供一些思路。

今天文章提供的代码可能并不是很完善,如果你有更好的解题思路,欢迎留言区指出。

相关文章
|
NoSQL 数据库 Redis
新鲜出炉面试题(三)
新鲜出炉面试题(三)
|
前端开发 数据库
新鲜出炉面试题(一)
春天到了,那颗躁动不安的心又踏上了面试之旅,菜鸟在前方探路,返回一手资料供你参考。
|
SQL 数据库 索引
新鲜出炉面试题(二)
今天是华为的初试,明天还有复试。快来看一下今天的题目吧。
|
存储 前端开发 JavaScript
🍪前端笔试系列 | 小米2020校招前端工程师笔试题
🍪前端笔试系列 | 小米2020校招前端工程师笔试题
531 9
🍪前端笔试系列 | 小米2020校招前端工程师笔试题
|
Java 程序员 Spring
聚能聊每周精选 第十五期
Hello! 各位社区小伙伴们!好久不见!“爱你就像,蓝天白云,晴空万里,突然暴风雨。”接下来,让我们一起回顾一下,本周都有哪些热议的话题?各位聊主与粉丝们又有哪些精彩的互动?他们之间又碰撞出了怎样的火花? .
3335 0
聚能聊每周精选 第十五期
|
程序员 API
聚能聊每周精选 第十三期
Hello! 各位社区小伙伴们!好久不见! “爱你就像,蓝天白云,晴空万里,突然暴风雨。” 接下来,让我们一起回顾一下,本周聚能聊里各位聊主与各位粉丝们有哪些精彩的互动!他们又碰撞出了怎样的火花!
3176 0
聚能聊每周精选 第十三期
|
程序员 UED
聚能聊每周精选 第十一期
各位社区小伙伴大家!让大家久等了,大家不要见怪啊!话不多说接下来我们来看看最近聚能聊里各位聊主和各位粉丝们又有哪些精彩互动,碰撞出怎样的火花,一起来回顾一下吧!!
4746 0
聚能聊每周精选 第十一期
|
安全 网络协议 Java
去腾讯面试,让做了几道JAVA笔试题,做对就给30K,邀你来战!
前几天去腾讯面试,让做一道JAVA笔试题,今天给大家整理了下。不知道我总结得对不,欢迎有不同的声音。 1、说几种常见的攻击方式及预防手段。
3528 0
|
Java Linux 程序员
聚能聊每周精选 第十八期
Hello! 各位社区小伙伴们!好久不见! “爱你就像,蓝天白云,晴空万里,突然暴风雨。” 接下来,让我们一起回顾一下,本周都有哪些热议的话题?各位聊主与粉丝们又有哪些精彩的互动?他们之间又碰撞出了怎样的火花? 接下来,让我们一起回顾一下,近期都有哪些热议的话题。
2773 0