经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 其他 » 职业生涯 » 查看文章
头条面试题:求用户在线峰值和持续时间
来源:cnblogs  作者:中阳里士  时间:2021/3/29 9:00:39  对本文有异议

前几天我的朋友面试头条,给出了这样一道面试题:

有一天的log的数据量,求一天中用户在线峰值和持续时间。

他面试结束后与我讨论,让我也做一下,我晚上就用了点时间做了这个题目。

写完之后我们讨论发现因为思路不同,且他的方法更好,就记录下来跟大家分享一下。

事先声明一个log实体:

  1. /// <summary>
  2. /// 登录日志
  3. /// </summary>
  4. public class Log
  5. {
  6. /// <summary>
  7. /// 登录时间
  8. /// </summary>
  9. public int LoginTime { get; set; }
  10. /// <summary>
  11. /// 登出时间
  12. /// </summary>
  13. public int LogoutTime { get; set; }
  14. }

因为只求峰值数据,太多的字段没有加。

创建假数据:

  1. //模拟数据
  2. var logs = new List<Log>{
  3. new Log{ LoginTime=2, LogoutTime=5 },
  4. new Log{ LoginTime=3, LogoutTime=6 },
  5. new Log{ LoginTime=3, LogoutTime=4 },
  6. new Log{ LoginTime=4, LogoutTime=8 },
  7. new Log{ LoginTime=4, LogoutTime=9 },
  8. new Log{ LoginTime=4, LogoutTime=10 },
  9. new Log{ LoginTime=3, LogoutTime=4 },
  10. new Log{ LoginTime=4, LogoutTime=8 },
  11. new Log{ LoginTime=5, LogoutTime=6 },
  12. };

 

以下是我的代码:

  1. #region 获取每个小时在线人数
  2.  
  3. //定义一个数组盛放每个小时的在线人数
  4. int[] logHigh = new int[24];
  5. int time = 0;
  6. while (time < 24)
  7. {
  8. logHigh[time] = 0;
  9. foreach (var log in logs)
  10. {
  11. if (time >= log.LoginTime && time < log.LogoutTime)
  12. {
  13. logHigh[time]++;
  14. }
  15. }
  16. time++;
  17. }
  18. #endregion
  19. #region 获取最大在线人数和持续时间
  20.  
  21. //获取最大在线人数
  22. var max = logHigh[0];
  23. var index = 0;
  24. for (int j = 1; j < logHigh.Length; j++)
  25. {
  26. if (max < logHigh[j])
  27. {
  28. max = logHigh[j];
  29. index = j;
  30. }
  31. }
  32. //获取最大在线人数持续时间
  33. var maxIndex = 0;
  34. for (var maxI = index + 1; maxI < logHigh.Length; maxI++)
  35. {
  36. if (logHigh[maxI] == max)
  37. {
  38. maxIndex = maxI;
  39. }
  40. else
  41. {
  42. continue;
  43. }
  44. }
  45. #endregion
  46. Console.WriteLine("最大在线人数是:" + max);
  47. Console.WriteLine($"起始时间是:{index},结束时间是:{maxIndex + 1},持续时间:{maxIndex + 1 - index}h");
  48. for (var i = 0; i < 24; i++)
  49. {
  50. Console.WriteLine($"时间在 {i} 到 {i + 1} 点之间在线人数是:{logHigh[i].ToString()}");
  51. }
  52. Console.ReadKey();

运行结果:

  

写完之后我们对结果,没有问题。又互相看了对方的代码,发现逻辑是不一样的。

以下贴出朋友的代码:

  1. //当天数据容器
  2. var array = new int[24];
  3. //初始化数据
  4. foreach (var item in logs)
  5. {
  6. //只记录当前在线人数即可
  7. for (int i = item.LoginTime; i < item.LogoutTime; i++)
  8. {
  9. array[i]++;
  10. }
  11. }
  12. //统计部分
  13. int biggest = 0; //峰值
  14. int biggestLength = 0; //持续时长
  15. int biggestTime = 0; //最大开始时间
  16.  
  17. for (int i = 0; i < array.Length; i++)
  18. {
  19. //当前在线人数
  20. var currentValue = array[i];
  21. //存储最大峰值
  22. if (currentValue > biggest)
  23. {
  24. biggest = currentValue;
  25. biggestLength = 0;
  26. biggestTime = i;
  27. }
  28. if (currentValue == biggest)
  29. biggestLength++;
  30. }
  31. //输出部分
  32. for (int i = 0; i < array.Length; i++)
  33. {
  34. Console.WriteLine($"当前时间:{i} \t 在线人数:{array[i]}");
  35. }
  36. Console.WriteLine($"当天最大峰值:{biggest}人,开始时间:{biggestTime}点,持续时间:{biggestLength}h");
  37. Console.ReadKey();

运行结果:

不知道大家看出来我们两个逻辑上有什么不同吗?

其实主要的不同是第一部分求每个小时在线人数的思路上的不同:

我的想法是轮询24小时,遍历log数据发现在遍历的时间内就+1;

他的思路是遍历log数据,在数据的开始结束时间内都+1。

他这样做的话就在复杂度上少了很多,至少比我少一半的复杂度。

这其实就是一道大厂非常喜欢考的逻辑算法的题目,我朋友这样的算法自然更好:逻辑清晰,复杂度低。

 

如果大家还有什么更好的解法欢迎写在下面。

原文链接:http://www.cnblogs.com/jingboweilan/p/14546613.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号