題目連結:
題目意譯:
你被給定 Leetcode 使用者行為的記錄檔,以及一個整數 k。這些記錄檔是以一個二維整數陣列 logs 所表示,其中 logs[i] = [IDi, timei] 代表著編號 IDi 的使用者在 timei 分鐘時執行了某個動作。
多個使用者可以同時執行動作,而一個使用者可以在同一分鐘內執行多個動作。
對於一個給定的使用者,其使用者活躍分鐘數(User Active Minutes,UAM)定義為該使用者在 Leetcode 執行動作的相異時間點數量(以分鐘為單位)。每一分鐘最多只能算一次,即便該分鐘中有多次的動作發生。
你需要計算出一個索引值從 1 開始且大小為 k 的陣列 answer,使得對於每個 j(1 ≦ j ≦ k),answer[j] 為 UAM 之值等於 j 的使用者數量。
回傳上述定義的陣列 answer。
限制:
1 ≦ logs.length ≦ 10 ^ 4
0 ≦ IDi ≦ 10 ^ 9
1 ≦ timei ≦ 10 ^ 5
k 位於範圍 [所有使用者中最大的 UAM 之值, 10 ^ 5] 中。
範例測資:
範例 1:
輸入: logs = [[0,5],[1,2],[0,2],[0,5],[1,3]], k = 5
輸出: [0,2,0,0,0]
解釋:
編號 0 的使用者在 5 、 2 和 5 分鐘時執行了一些動作。因此他的 UAM 之值為 2(5 分鐘那一刻只會被算一次)。
編號 1 的使用者在 2 和 3 分鐘時執行了一些動作。因此他的 UAM 之值為 2。
由於兩個使用者的 UAM 之值皆為 2,因此 answer[2] 為 2,而其餘的 answer[j] 之值皆為 0。
範例 2:
輸入: logs = [[1,1],[2,2],[2,3]], k = 4
輸出: [1,1,0,0]
解釋:
編號 1 的使用者在 1 分鐘時執行了一個動作。因此他的 UAM 之值為 1。
編號 2 的使用者在 2 和 3 分鐘時執行了一些動作。因此他的 UAM 之值為 2。
有一個使用者 UAM 之值為 1,另一個為 2。
因此,answer[1] = 1 、 answer[2] = 1,而其餘之值皆為 0。
解題思維:
首先,我們把 logs 按照時間由小排到大(大到小也可以)。時間一樣的話按 ID 由小排到大(一樣,可以大到小)。現在 logs 中,時間一樣的動作會排在一起,而同一時間段中同一個使用者做動作的記錄會被排在一起。
接著用一個雜湊表(Hash Table)來記錄每一個使用者的 UAM。之後掃過一次排序後的 logs:
當遇到一個「新的」時間段時,也就是說遇到某個 logs[i][1] != logs[i - 1][1] 時(注:開頭的 logs[0] 因為沒有「前一個」記錄,所以算這邊),代表現在先前「看過」的 ID 可以當作沒看過了。因為現在是新的時間點,可以重新計算。
反之,如果還在同一個時間點內,且遇到「新的」ID 時,代表現在這位使用者的 UAM 可以加 1。因為根據先前的排序條件,在同一個時間點中所有 ID 一樣的動作將會排在同一個區塊中。因此看到與先前不同的 ID,代表著這是由這個使用者在此時間點做出的動作序列之「開頭」。
最後掃過一次雜湊表中的內容,把每一位使用者的 UAM 擷取出來並統計各個 UAM 的出現次數便可以得到陣列 answer。
此次分享到此為止,如有任何更加簡潔的想法或是有說明不清楚之地方,也煩請各位大大撥冗討論。