题目地址:
https://leetcode.com/problems/analyze-user-website-visit-pattern/
给定三个等长的数组,数组 A A A是一系列用户,数组 B B B是这些用户访问网站的时间戳,数组 C C C是用户访问的网站。某个用户按时间依次访问的网站如果长度 l l l大于 3 3 3,就可以取出 ( l 3 ) l\choose3 (3l)个三元组。问这些三元组里被最多用户访问过的组合是哪个。如果答案有多个则返回字典序最小的那个三元组。题目保证至少有一个用户访问了三个或以上的网站。
先将用户、时间戳和网站做成一个类,然后按照时间戳排序,再用一个哈希表存一下每个用户访问网站的序列。接着对每个用户,枚举三元组,并对三元组计数。注意,同一个三元组对同一个用户而言,只能计数一次。最后查找一下计数次数最多、字典序最小的三元组即可。代码如下:
import java.util.*;
public class Solution {
class Visit {
String username, website;
int timestamp;
public Visit(String username, String website, int timestamp) {
this.username = username;
this.website = website;
this.timestamp = timestamp;
}
}
public List<String> mostVisitedPattern(String[] username, int[] timestamp, String[] website) {
int n = username.length;
// 先存一下Visit,然后对其按照时间戳排序
List<Visit> list = new ArrayList<>();
for (int i = 0; i < n; i++) {
list.add(new Visit(username[i], website[i], timestamp[i]));
}
list.sort((v1, v2) -> Integer.compare(v1.timestamp, v2.timestamp));
// 存一下每个用户访问网站的序列
Map<String, List<String>> map = new HashMap<>();
for (int i = 0; i < n; i++) {
Visit visit = list.get(i);
map.putIfAbsent(visit.username, new ArrayList<>());
map.get(visit.username).add(visit.website);
}
// 对每个用户枚举三元组
Map<List<String>, Integer> count = new HashMap<>();
for (Map.Entry<String, List<String>> entry : map.entrySet()) {
List<String> webList = entry.getValue();
if (webList.size() >= 3) {
// 这里对三元组要去重,因为他们的计数只能加1
Set<List<String>> set = new HashSet<>();
for (int i = 0; i < webList.size() - 2; i++) {
for (int j = i + 1; j < webList.size() - 1; j++) {
for (int k = j + 1; k < webList.size(); k++) {
List<String> tuple = Arrays.asList(webList.get(i), webList.get(j), webList.get(k));
set.add(tuple);
}
}
}
// 在哈希表里的计数加1
for (List<String> tuple : set) {
count.put(tuple, count.getOrDefault(tuple, 0) + 1);
}
}
}
// 最后找一下出现次数最多、字典序最小的三元组
List<String> res = new ArrayList<>();
int maxCount = 0;
for (Map.Entry<List<String>, Integer> entry : count.entrySet()) {
if (entry.getValue() > maxCount) {
maxCount = entry.getValue();
res = entry.getKey();
} else if (entry.getValue() == maxCount && compare(entry.getKey(), res) < 0) {
res = entry.getKey();
}
}
return res;
}
private int compare(List<String> l1, List<String> l2) {
for (int i = 0; i < 3; i++) {
int comp = l1.get(i).compareTo(l2.get(i));
if (comp != 0) {
return comp;
}
}
return 0;
}
}
时间复杂度 O ( n 3 ) O(n^3) O(n3), n n n是数组长度,空间 O ( n ) O(n) O(n)。