zoukankan      html  css  js  c++  java
  • 头条面试题:求用户在线峰值和持续时间

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

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

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

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

    事先声明一个log实体:

        /// <summary>
        /// 登录日志
        /// </summary>
        public class Log
        {
            /// <summary>
            /// 登录时间
            /// </summary>
            public int LoginTime { get; set; }
            /// <summary>
            /// 登出时间
            /// </summary>
            public int LogoutTime { get; set; }
        }

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

    创建假数据:

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

    以下是我的代码:

                #region 获取每个小时在线人数
    
                //定义一个数组盛放每个小时的在线人数
                int[] logHigh = new int[24];
                int time = 0;
                while (time < 24)
                {
                    logHigh[time] = 0;
                    foreach (var log in logs)
                    {
                        if (time >= log.LoginTime && time < log.LogoutTime)
                        {
                            logHigh[time]++;
                        }
                    }
                    time++;
                }
    
                #endregion
                #region 获取最大在线人数和持续时间
    
                //获取最大在线人数
                var max = logHigh[0];
                var index = 0;
                for (int j = 1; j < logHigh.Length; j++)
                {
                    if (max < logHigh[j])
                    {
                        max = logHigh[j];
                        index = j;
                    }
                }
                //获取最大在线人数持续时间
                var maxIndex = 0;
                for (var maxI = index + 1; maxI < logHigh.Length; maxI++)
                {
                    if (logHigh[maxI] == max)
                    {
                        maxIndex = maxI;
                    }
                    else
                    {
                        continue;
                    }
    
                }
    
                #endregion
                Console.WriteLine("最大在线人数是:" + max);
                Console.WriteLine($"起始时间是:{index},结束时间是:{maxIndex + 1},持续时间:{maxIndex + 1 - index}h");
    
                for (var i = 0; i < 24; i++)
                {
                    Console.WriteLine($"时间在 {i} 到 {i + 1} 点之间在线人数是:{logHigh[i].ToString()}");
                }
                Console.ReadKey();    

    运行结果:

      

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

    以下贴出朋友的代码:

                //当天数据容器
                var array = new int[24];
    
                //初始化数据
                foreach (var item in logs)
                {
                    //只记录当前在线人数即可
                    for (int i = item.LoginTime; i < item.LogoutTime; i++)
                    {
                        array[i]++;
                    }
                }
    
                //统计部分
                int biggest = 0;        //峰值
                int biggestLength = 0;  //持续时长
                int biggestTime = 0;    //最大开始时间
    
                for (int i = 0; i < array.Length; i++)
                {
                    //当前在线人数
                    var currentValue = array[i];
    
                    //存储最大峰值
                    if (currentValue > biggest)
                    {
                        biggest = currentValue;
                        biggestLength = 0;
                        biggestTime = i;
                    }
    
                    if (currentValue == biggest)
                        biggestLength++;
                }
    
                //输出部分
                for (int i = 0; i < array.Length; i++)
                {
                    Console.WriteLine($"当前时间:{i} 	 在线人数:{array[i]}");
                }
    
                Console.WriteLine($"当天最大峰值:{biggest}人,开始时间:{biggestTime}点,持续时间:{biggestLength}h");
                Console.ReadKey();    

    运行结果:

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

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

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

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

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

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

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

    源码git下载地址:https://gitee.com/jingboweilanGO/demo_-log-high.git

    如果觉得不错,可以推荐收藏一下,让我也更有动力。
  • 相关阅读:
    linux一些常用命令
    imageMagick
    nginx安装配置
    数据库操作(六)、Date函数
    数据库操作(五)、聚合函数,分组
    JQuery(一)
    数据库小结(二)
    数据库操作(四)、标量函数
    数据库操作(三)
    C#基础(六)
  • 原文地址:https://www.cnblogs.com/jingboweilan/p/14546613.html
Copyright © 2011-2022 走看看