您的位置:首页 > 职场人生

头条面试题:求用户在线峰值和持续时间

2021-03-16 22:59 411 查看

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

有一天的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} \t 在线人数:{array[i]}");
}

Console.WriteLine($"当天最大峰值:{biggest}人,开始时间:{biggestTime}点,持续时间:{biggestLength}h");
Console.ReadKey();

运行结果:

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

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

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

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

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

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

 

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

 

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

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: