在面试的时候遇到这样一道题。给定一些用户登录的日志,计算任意时间的在线人数。其中用户登录日志包括如下信息:
type LoginLog struct {
userId int
loginTime int
logoutTime int
}
根据题目,一天24小时,我们有一堆的用户登录日志。简单的做法是我们遍历获取日志,然后对于用户在线的这段时间,对每一个时间点对在线人数加一。则程序如下:
func calOnlineUserCount(logList []*LoginLog) map[int]int {
var timeToOnlineUserCountMap = make(map[int]int)
for _, log := range logList {
for i := log.loginTime; i <= log.logoutTime; i++ {
timeToOnlineUserCountMap[i]++
}
}
return timeToOnlineUserCountMap
}
可以知道,这种方法的时间复杂度为O(kn)。在面试的时候面试官会希望给出O(n)事件复杂度的解法。
简单考虑一下,如果我们知道k时间的在线人数,我们很容易知道k+1时间的在线认识:
k+1时刻的在线人数 = k时刻在线人数 + k+1时刻上线人数 - k+1时刻下线人数
则我们可以获得这样的解:
func calOnlineUserCount(logList []*LoginLog) map[int]int {
var timeToOnlineUserCountMap = make(map[int]int)
var timeToLoginUserCountMap = make(map[int]int)
var timeToLogoutUserCountMap = make(map[int]int)
for _, log := range logList {
timeToLoginUserCountMap[log.loginTime]++
timeToLogoutUserCountMap[log.logoutTime]++
}
var startTime int // 根据统计时间
var endTime int // 根据统计时间
for i := startTime; i <= endTime; i++ {
timeToOnlineUserCountMap[i] = max(timeToOnlineUserCountMap[i-1] + timeToLoginUserCountMap[i] - timeToLogoutUserCountMap[i], 0)
}
return timeToOnlineUserCountMap
}