頭條面試題:求用戶在線峰值和持續時間


前幾天我的朋友面試頭條,給出了這樣一道面試題:

有一天的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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM