1.已知用户好友关系(平均100个好友),设计查看和另一个用户是几度人脉的功能?

在社交网络中,有一个六度分割理论,具体是说,你与世界上的另一个人间隔的关系不会超过六度,也就是说平均只需要六步就可以联系到任何两个互不相识的人。

说明:

一度:A<->B :A和B是直接好友,此时A和B是一度好友

二度:A<->B<->C,A和B是好友,B和C是好友,所以A和C是两度好友

以此类推

思路1:

建立一张用户关系表:(key:维护用户的ID,value维护用户的好友ID集合set)

一度:A<->B , 直接查询用户关系表(可以用缓存优化,key:用户id,value:用户的好友set)

二度:A<->B<->C,首先排除一度的情况,然后拿A的好友和C的好友,两个集合取交集

三度:A<->B<->C<->D,拿A的二度好友(提前计算好的),和D的一度好友,取交集

四度及以上的:显示三度+

思路2:图计算(最短路径)(面试官可能追问图计算怎么实现)

两种算法参考:

深度优先搜索算法和广度优先搜索算法都是基于“图”数据结构

1.深度优先搜索算法

2.广度优先搜索算法

2.基于redis设计限流器

需求:限定用户的某个行为在指定时间T内,只允许发生N次。假设T为1秒钟,N为1000次。

思路1:利用 zset实现滑动窗口限流的代码(防止流量突增

以限制用户行为为例子,比如一秒内进行某个操作50次,这种行为应该进行限制

滑动窗口就是记录一个滑动的时间窗口内的操作次数,操作次数超过阈值则进行限流

在实际操作zset的过程中,只需要保留在这个滑动时间窗口以内的数据,其他的数据不处理即可。

  • 每个用户的行为采用一个zset存储,score为毫秒时间戳,value也使用毫秒时间戳(比UUID更加节省内存)
  • 只保留滑动窗口时间内的行为记录,如果zset为空,则移除zset,不再占用内存(节省内存)

 Lua脚本实现:

var counterLuaScript = `-- 记录行为redis.pcall("zadd", KEYS[1], ARGV[1], ARGV[1]); -- value 和 score 都使用纳秒时间戳,即ARGV[1]redis.pcall("zremrangebyscore", KEYS[1], 0, ARGV[2]); -- 移除时间窗口之前的行为记录,剩下的都是时间窗口内的local count = redis.pcall("zcard", KEYS[1]); -- 获取窗口内的行为数量redis.pcall("expire", KEYS[1], ARGV[3]); -- 设置 zset 过期时间,避免冷用户持续占用内存return count -- 返回窗口内行为数量`

JAVA代码实现:

/*** redis使用zset实现滑动窗口计数* key:sliding_window_用户登录名* value(zset):value=当前时间戳,score=当前时间戳**/
@Component
@Slf4j
public class SlidingWindowCounter {/*** redis key前缀*/private static final String SLIDING_WINDOW = "sliding_window_";@Autowiredprivate RedisTemplate redisTemplate;* 判断key的value中的有效访问次数是否超过最大限定值maxCount* 判断与数量增长分开处理** @param key            redis key* @param windowInSecond 窗口间隔,秒* @param maxCount       最大计数* @return 是 or 否public boolean overMaxCount(String key, int windowInSecond, long maxCount) {key = SLIDING_WINDOW + key;log.info("redis key = {}", key);// 当前时间long currentMs = System.currentTimeMillis();// 窗口开始时间long windowStartMs = currentMs - windowInSecond * 1000L;// 按score统计key的value中的有效数量Long count = redisTemplate.opsForZSet().count(key, windowStartMs, currentMs);// 已访问次数 >= 最大可访问值return count >= maxCount;}* 判断key的value中的有效访问次数是否超过最大限定值maxCount,若没超过,调用increment方法,将窗口内的访问数加一* 判断与数量增长同步处理* @return 可访问 or 不可访问public boolean canAccess(String key, int windowInSecond, long maxCount) {//按key统计集合中的有效数量Long count = redisTemplate.opsForZSet().zCard(key);if (count < maxCount) {increment(key, windowInSecond);return true;} else {return false;}* 滑动窗口计数增长public void increment(String key, Integer windowInSecond) {long windowStartMs = currentMs - windowInSecond * 1000;// 单例模式(提升性能)ZSetOperations zSetOperations = redisTemplate.opsForZSet();// 清除窗口过期成员zSetOperations.removeRangeByScore(key, 0, windowStartMs);// 添加当前时间 value=当前时间戳 score=当前时间戳zSetOperations.add(key, String.valueOf(currentMs), currentMs);// 设置key过期时间redisTemplate.expire(key, windowInSecond, TimeUnit.SECONDS);

思路2:令牌桶:计数器,定时往桶里加元素,借助lua脚本判断桶是否满了,取令牌也用lua、

public Map<string, object=""> startLingpaitong(Map<string, object=""> paramMap) {String redisKey = "lingpaitong";String token = redisTemplate.opsForList().leftPop(redisKey).toString();//正常情况需要验证是否合法,防止篡改if (StringUtils.isEmpty(token)) {throw new RuntimeException("令牌桶拒绝");}Map<string, object=""> map = new HashMap<>();map.put("success", "success");return map;}@Scheduled(cron="*/1 * * * * ?")private void process(){//一次性生产两个System.out.println("正在消费。。。。。。");for (int i = 0; i < 2; i++) {redisTemplate.opsForList().rightPush(redisKey, i);}}

3.10亿数组去重排序

思路1:分而治之

借助hash算法思想,把一个大文件哈希分割到多个小文件中,而哈希冲突的数字

一定会在同一个小文件中,从而保证了子问题的独立性,然后就可以单独对小文件通过快速排序来去重。

这样就通过分而治之解决了几G数据进行内排序的问题。

虽然哈希分割文件是O(n)的时间复杂度,但总的效率仍是依从快速排序的时间复杂度O(n*logn)。

分而治之有个好处就是借助子问题的独立性可以利用多核来做并行处理,甚至做分布式处理

思路2:位图bitMap

1G内存可以放多大范围的数据?1GB=10亿字节=80亿bit

如果超过了?用两个bitmap,两个不够用3个,处理完再做合并

bitmap:数据范围已知,并且内存放得下

bitMap介绍:

BitMap,即位图,使用每个位表示某种状态,适合处理整型的海量数据。本质上是哈希表的一种应用实现,原理也很简单,给定一个int整型数据,将该int整数映射到对应的位上,并将该位由0改为1。例如:

// 存在一个int整型数组
int[] arr = new int[]{6,2,7,14,3};

arr数组中最大值为14,考虑位的下标从0开始,需要长度为15的bit,因此每个bit代表着0~14的整数,如图所示:

很显然,使用 BitMap 存储这个数组只使用了使用15bit,而使用 HashSet 或 HashMap 的话,一个数组元素会存储为一个int,而一个int占4个byte,即4*8=32bit,这里有5个数组元素则需要5*32=160bit,这样的话,使用 BitMap 存储一个元素则可以节省32倍的内存空间。因此,BitMap 的优势就不言而喻了。

结构决定功能,BitMap非常适合对整型的海量数据进行查询统计、排序、去重;适合对两个集合做交集、并集运算,但不支持非运算,如果需要进行非运算则需要提供一个全量的BitMap才行。

4.100万考生,高考排名怎么做?

思路1:计数排序

假设最高分是700

700,699,698.。。500。。。。4,3,2,1,0

每个分数一个bucket,然后存储分数对应的学生数量

假设我是600分,就统计大于600分的人数总和,600分的排名就是人数总和的后一名

5.游戏top实时排行榜

需求:实时获取游戏等级前100名的用户ID,并进行排序

思路1:小顶堆

6.多租户场景下,分表按照companyId分,会有每张表数据不均匀的情况,怎么处理?

从业务入手,可以建立vip库,分等级,不同级别有不同的维护策略

7.设计微信摇一摇功能(设计微信附近的人功能)

思路1:Geohash

JAVA面试-系统设计题相关推荐

  1. 阿里最全Java面试100题汇总:涵盖天猫、蚂蚁金服等面试题!含答案~

    [阿里天猫.蚂蚁.钉钉面试题目] 1.微信红包怎么实现. 2.海量数据分析. 3.测试职位问的线程安全和非线程安全. 4.HTTP2.0.thrift. 5.面试电话沟通可能先让自我介绍. 6.分布式 ...

  2. 百度统计 java 实现思路_2019社招阿里、腾讯、蚂蚁金服「四面」Java面试真题分享...

    在过去很长一段时间内,国内互联网一直处于三足鼎立状态,BAT即百度.阿里巴巴.腾讯.而在最新的互联网企业价值榜上,百度却被蚂蚁金服挤出前三的位置. 能够进一线互联网公司,是大部分程序员奋斗的目标,有很 ...

  3. java gui中文变方块_150道Java面试基础题(含答案)

    1)Java 中能创建 volatile 数组吗? 能,Java 中可以创建 volatile 类型数组,不过只是一个指向数组的引用,而不是整个数组.我的意思是,如果改变引用指向的数组,将会受到 vo ...

  4. java面试基础题整理(二)

    java面试基础题整理 文章目录 java面试基础题整理 前端技术(HTML.CSS.JS.JQuery等) 在js中怎么样验证数字? js中如何给string这个类型加方法? 谈谈js的定时器? 请 ...

  5. 2021大厂Java面试真题(一)

    2021大厂Java面试真题(一) 大厂面试的基本流程 以下是一些大厂面试的基本流程,大家可以参考下: 字节跳动 阿里 腾讯 网易游戏 面试前需要准备: \1. **Java 八股文:**了解常考的题 ...

  6. 精选 2021 年大厂高频 Java 面试真题集锦(含答案),面试一路开挂

    本文涵盖了阿里巴巴.腾讯.字节跳动.京东.华为等大厂的 Java 面试真题,不管你是要面试大厂还是普通的互联网公司,这些面试题对你肯定是有帮助的,毕竟大厂一定是行业的发展方向标杆,很多公司的面试官同样 ...

  7. 精选2022年大厂高频Java面试真题集锦(含答案),面试一路开挂

    本文涵盖了阿里巴巴.腾讯.字节跳动.京东.华为等大厂的Java面试真题,不管你是要面试大厂还是普通的互联网公司,这些面试题对你肯定是有帮助的,毕竟大厂一定是行业的发展方向标杆,很多公司的面试官同样会研 ...

  8. 最新Java面试300题:腾讯T4面试+美团+京东+拼多多(文末答案附赠)

    数据库原理 MYISAM与innodb搜索引擎原理MyISAM引擎使用B+Tree作为索引结构,叶节点的data域存放的是数据记录的地址.其采用索引文件与数据文件,索引文件只存放索引,叶子节点存放数据 ...

  9. 2021大厂Java面试真题(二)

    2021大厂Java面试真题(二) 2021 [阿里]面试真题: 1.TCP 和 UDP 区别? TCP 基于连接,UDP 基于无连接. TCP 要求系统资源较多,UDP 较少. UDP 程序结构较简 ...

最新文章

  1. ORACLE等待事件:direct path write
  2. 秀秀博客大赛50强的礼物
  3. weblogic管理1——创建 和 删除一个domain
  4. Oracle_11g_R2安装手册(图文教程)
  5. 53 SD配置-定价配置-定义条件排斥组
  6. SpringBoot——Quartz定时框架的使用详解和总结
  7. vant表单点击提交没有触发验证_jquery.validate不用submit提交,用js提交的,怎么触发验证啊?...
  8. [Flink]Flink的window介绍
  9. [转载]Spring zuul日志配置
  10. 2022 年云计算发展趋势
  11. 安卓手机远程连接linux系统,电脑(Linux/Windows)使用SSH远程登录安卓(Android)手机实现无线传输和管理文件(图文详解)-Go语言中文社区...
  12. 显卡刷bios变砖怎么办--关于矿卡,一些惊呆我的骚操作
  13. 游记-NOI2019(hzy的退役日志)
  14. 关于EBGP用回环口起邻居遇到的问题
  15. 北大计算机论文答辩,自考同路人:在北大参加论文答辩的全过程
  16. 第二眼美女、IEO 和区分 FIND
  17. BUUCTF [FlareOn2]elfie
  18. 艾永亮:为什么国内品牌很难在市场中生存下去
  19. 计算机修改人类记忆曲线,Memory Helper - 艾宾浩斯遗忘曲线记忆助手
  20. ICS大作业--程序人生

热门文章

  1. 易语言对象--Word之精确定位表格单元格中并写入文本
  2. 生成哑变量的几种方法
  3. python中的位运算符
  4. 普及计算机知识的意义,计算机在当今社会的重要性
  5. 如何在论文中表格和图片变成引用格式,实现ctrl访问
  6. Debian11.5 最小化安装后更改主机名、安装桌面、设置默认语言、时区、静态IP、局域网DNS等
  7. 一个主机可以接几个php,一台主机如何连接两个显示器
  8. PAT A1010.Radix 二分法
  9. 【区块链 | 数据上链】星火链网、蚂蚁联盟链等区块链业务系统开发指南
  10. java u盘_Java检测Windows的U盘插入详解