Problem

You are given a 2D 0-indexed array of strings, access_times, with size n. For each i where 0 <= i <= n - 1, access_times[i][0] represents the name of an employee, and access_times[i][1] represents the access time of that employee. All entries in access_times are within the same day.

The access time is represented as four digits using a 24-hour time format, for example, "0800" or "2250".

An employee is said to be high-access if he has accessed the system three or more times within a one-hour period.

Times with exactly one hour of difference are not considered part of the same one-hour period. For example, "0815" and "0915" are not part of the same one-hour period.

Access times at the start and end of the day are not counted within the same one-hour period. For example, "0005" and "2350" are not part of the same one-hour period.

Return a list that contains the names ofhigh-access employees with any order you want.

Examples

Example 1

1
2
3
4
5
Input: access_times = [["a","0549"],["b","0457"],["a","0532"],["a","0621"],["b","0540"]]
Output: ["a"]
Explanation: "a" has three access times in the one-hour period of [05:32, 06:31] which are 05:32, 05:49, and 06:21.
But "b" does not have more than two access times at all.
So the answer is ["a"].

Example 2

1
2
3
4
5
Input: access_times = [["d","0002"],["c","0808"],["c","0829"],["e","0215"],["d","1508"],["d","1444"],["d","1410"],["c","0809"]]
Output: ["c","d"]
Explanation: "c" has three access times in the one-hour period of [08:08, 09:07] which are 08:08, 08:09, and 08:29.
"d" has also three access times in the one-hour period of [14:10, 15:09] which are 14:10, 14:44, and 15:08.
However, "e" has just one access time, so it can not be in the answer and the final answer is ["c","d"].

Example 3

1
2
3
4
5
Input: access_times = [["cd","1025"],["ab","1025"],["cd","1046"],["cd","1055"],["ab","1124"],["ab","1120"]]
Output: ["ab","cd"]
Explanation: "ab" has three access times in the one-hour period of [10:25, 11:24] which are 10:25, 11:20, and 11:24.
"cd" has also three access times in the one-hour period of [10:25, 11:24] which are 10:25, 10:46, and 10:55.
So the answer is ["ab","cd"].

Constraints

  • 1 <= access_times.length <= 100
  • access_times[i].length == 2
  • 1 <= access_times[i][0].length <= 10
  • access_times[i][0] consists only of English small letters.
  • access_times[i][1].length == 4
  • access_times[i][1] is in 24-hour time format.
  • access_times[i][1] consists only of '0' to '9'.

Solution

Method 1 – Sliding Window with Sorting

Intuition

If we sort each employee’s access times, we can efficiently check for any three accesses within a one-hour window using a sliding window approach. This works because the times are in a fixed format and can be compared as integers.

Approach

  1. Group all access times by employee name.
  2. Convert each time string (e.g., “0549”) to minutes since midnight for easy comparison.
  3. For each employee, sort their access times.
  4. Use a sliding window of size 3 to check if the difference between the earliest and latest in the window is less than 60 minutes.
  5. If such a window exists, add the employee to the answer list.
  6. Return the list of high-access employees.

Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
public:
    vector<string> findHighAccessEmployees(vector<vector<string>>& access_times) {
        unordered_map<string, vector<int>> m;
        for (auto& x : access_times) {
            int t = stoi(x[1].substr(0,2)) * 60 + stoi(x[1].substr(2,2));
            m[x[0]].push_back(t);
        }
        vector<string> ans;
        for (auto& [name, times] : m) {
            sort(times.begin(), times.end());
            for (int i = 2; i < times.size(); ++i) {
                if (times[i] - times[i-2] < 60) {
                    ans.push_back(name);
                    break;
                }
            }
        }
        return ans;
    }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
func findHighAccessEmployees(accessTimes [][]string) []string {
    m := map[string][]int{}
    for _, x := range accessTimes {
        h := (int(x[1][0]-'0')*10 + int(x[1][1]-'0')) * 60
        min := int(x[1][2]-'0')*10 + int(x[1][3]-'0')
        t := h + min
        m[x[0]] = append(m[x[0]], t)
    }
    ans := []string{}
    for name, times := range m {
        sort.Ints(times)
        for i := 2; i < len(times); i++ {
            if times[i]-times[i-2] < 60 {
                ans = append(ans, name)
                break
            }
        }
    }
    return ans
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
    public List<String> findHighAccessEmployees(List<List<String>> accessTimes) {
        Map<String, List<Integer>> m = new HashMap<>();
        for (List<String> x : accessTimes) {
            int t = Integer.parseInt(x.get(1).substring(0,2)) * 60 + Integer.parseInt(x.get(1).substring(2,2));
            m.computeIfAbsent(x.get(0), k -> new ArrayList<>()).add(t);
        }
        List<String> ans = new ArrayList<>();
        for (var e : m.entrySet()) {
            List<Integer> times = e.getValue();
            Collections.sort(times);
            for (int i = 2; i < times.size(); ++i) {
                if (times.get(i) - times.get(i-2) < 60) {
                    ans.add(e.getKey());
                    break;
                }
            }
        }
        return ans;
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
    fun findHighAccessEmployees(accessTimes: List<List<String>>): List<String> {
        val m = mutableMapOf<String, MutableList<Int>>() 
        for (x in accessTimes) {
            val t = x[1].substring(0,2).toInt() * 60 + x[1].substring(2,4).toInt()
            m.getOrPut(x[0]) { mutableListOf() }.add(t)
        }
        val ans = mutableListOf<String>()
        for ((name, times) in m) {
            times.sort()
            for (i in 2 until times.size) {
                if (times[i] - times[i-2] < 60) {
                    ans.add(name)
                    break
                }
            }
        }
        return ans
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
class Solution:
    def findHighAccessEmployees(self, access_times: list[list[str]]) -> list[str]:
        m: dict[str, list[int]] = {}
        for name, t in access_times:
            mins = int(t[:2]) * 60 + int(t[2:])
            m.setdefault(name, []).append(mins)
        ans: list[str] = []
        for name, times in m.items():
            times.sort()
            for i in range(2, len(times)):
                if times[i] - times[i-2] < 60:
                    ans.append(name)
                    break
        return ans
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
impl Solution {
    pub fn find_high_access_employees(access_times: Vec<Vec<String>>) -> Vec<String> {
        use std::collections::HashMap;
        let mut m: HashMap<String, Vec<i32>> = HashMap::new();
        for x in &access_times {
            let t = x[1][..2].parse::<i32>().unwrap() * 60 + x[1][2..].parse::<i32>().unwrap();
            m.entry(x[0].clone()).or_default().push(t);
        }
        let mut ans = vec![];
        for (name, times) in m.iter_mut() {
            times.sort();
            for i in 2..times.len() {
                if times[i] - times[i-2] < 60 {
                    ans.push(name.clone());
                    break;
                }
            }
        }
        ans
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
    findHighAccessEmployees(accessTimes: string[][]): string[] {
        const m: Record<string, number[]> = {};
        for (const [name, t] of accessTimes) {
            const mins = parseInt(t.slice(0,2)) * 60 + parseInt(t.slice(2));
            if (!m[name]) m[name] = [];
            m[name].push(mins);
        }
        const ans: string[] = [];
        for (const name in m) {
            m[name].sort((a, b) => a - b);
            for (let i = 2; i < m[name].length; ++i) {
                if (m[name][i] - m[name][i-2] < 60) {
                    ans.push(name);
                    break;
                }
            }
        }
        return ans;
    }
}

Complexity

  • ⏰ Time complexity: O(n log n) per employee, where n is the number of access times for that employee, due to sorting. Overall, O(N log K), where N is total records and K is max accesses per employee.
  • 🧺 Space complexity: O(N), for storing all access times grouped by employee.