1152. Analyze User Website Visit Pattern
T: O(n^3)
S: O(n)
class Solution {
class WebData {
String website;
int timestamp;
WebData(String website, int timestamp) {
this.website = website;
this.timestamp = timestamp;
}
}
public List<String> mostVisitedPattern(String[] username, int[] timestamp, String[] website) {
int n = username.length;
Map<String, List<WebData>> map = new HashMap<>();
for (int i = 0; i < n; i++) {
map.putIfAbsent(username[i], new ArrayList<>());
map.get(username[i]).add(new WebData(website[i], timestamp[i]));
}
Map<String, Integer> countMap = new HashMap<>();
String res = "";
for (String name : map.keySet()) {
// why set, ๅ ็บไธๆจฃ็ name, ๅฆๆๅบ็พไธๆจฃ็ pattern, ๅช่ฝ็ฎไธๆฌก, ๆไปฅๅไธๅ name ๅจ่จ็ฎๆ, ้ฟๅ
ไธๆจฃ็ pattern ่ขซ้่ค่จ็ฎ
// ๅฐไธๅname ๆ, set ๅฐฑ้็ฝฎไบ
Set<String> set = new HashSet<>();
List<WebData> list = map.get(name);
Collections.sort(list, (a, b) -> a.timestamp - b.timestamp); // ้ๆฏ้่ฆๆๅบ, ๆธฌ่ณtimstampๅฏ่ฝไธๆๅบ
// ๅ ็บ pattern ๆฏไธๅwebsite็ตๆ็, ๆไปฅๅ james ๆ 4ๅ็ถฒ็ซ "home","cart","maps","home"
// ้ๆจฃ่ฆ 4ๅ3ๅปๆๅ็ตๅๅบไพๆๆๅฏ่ฝ็ pattern, naive ๅฐฑๆฏ่ท n^3
for (int i = 0; i < list.size(); i++) {
for (int j = i+1; j < list.size(); j++) {
for (int k = j+1; k < list.size(); k++) {
String pattern = list.get(i).website + " " + list.get(j).website + " " + list.get(k).website;
if (!set.contains(pattern)) {
countMap.put(pattern, countMap.getOrDefault(pattern, 0)+1); // ไธๅname, ไธๆจฃ็ pattern count++
set.add(pattern); //้ฟๅ
ไธๆจฃname, ไธๆจฃ็pattern ่ขซ้่ค่จ็ฎ
}
// res ้ๆฒๅผๆ, ็ตฆๅpattern
// ๆฐ็ pattern count ๆฏ่ผๅคงๆ, ๆดๆฐ
// count ไธๆจฃ็ๆๅ ็จ lexicographically smallest such pattern
if ("".equals(res) || countMap.get(pattern) > countMap.get(res) ||
(countMap.get(pattern) == countMap.get(res) && res.compareTo(pattern) > 0)) {
res = pattern;
}
}
}
}
}
return Arrays.asList(res.split(" ")); // ๅๅณ้ๅฏไธ็ pattern
}
}
/*
["joe","home",1],["joe","about",2],["joe","career",3],["james","home",4],["james","cart",5],["james","maps",6],["james","home",7],["mary","home",8],["mary","about",9], and ["mary","career",10].
home about career
"home","cart","maps","home"
"home","about","career"
map
<name, pattern list>
-> pattern list should sort by timestamp
for each name
get list by name
build pattern use loop n^3 (exclude deplicate pattern count in same name), if another name deplicate pattern count is ok
at last if count is same, use lexicographically smallest such pattern
at last, only one pattern is the output
T: O(n^3)
*/
```java
class Solution {
private record WebHistory(String website, int timestamp) {};
public List<String> mostVisitedPattern(String[] username, int[] timestamp, String[] website) {
Map<String, List<WebHistory>> nameToHistory = new HashMap<>();
Map<String, Integer> visitedCount = new HashMap<>();
for (int i = 0; i < username.length; i++) {
nameToHistory.computeIfAbsent(username[i], k -> new ArrayList<>()).add(new WebHistory(website[i], timestamp[i]));
}
String maxPattern = "";
int max = 0;
for (String name : nameToHistory.keySet()) { // worst 1 (if only one name
List<WebHistory> history = nameToHistory.get(name);
history.sort((a, b) -> a.timestamp - b.timestamp); // worst nlogn (only one name, time len are n)
Set<String> set = new HashSet<>(); // remember don't count duplicated pattern for same name
for (int i = 0; i < history.size()-2; i++) { // O(n^3)
for (int j = i+1; j < history.size()-1; j++) {
for (int k = j+1; k < history.size(); k++) {
StringBuilder websites = new StringBuilder();
websites.append(history.get(i).website).append(" ")
.append(history.get(j).website).append(" ")
.append(history.get(k).website);
String pattern = websites.toString();
if (!set.contains(pattern)) {
visitedCount.put(pattern, visitedCount.getOrDefault(pattern, 0)+1);
set.add(pattern);
}
// compare immideiatly is faster than sort all later
if ("".equals(maxPattern) || visitedCount.get(pattern) > max
|| visitedCount.get(pattern) == max && maxPattern.compareTo(pattern) > 0) {
maxPattern = pattern;
max = visitedCount.get(pattern);
}
}
}
}
}
// List<String> result = new ArrayList<>(visitedCount.keySet());
// result.sort((a, b) -> {
// if (visitedCount.get(a) == visitedCount.get(b)) {
// return a.compareTo(b);
// }
// return visitedCount.get(b) - visitedCount.get(a);
// });
List<String> res = new ArrayList<>();
for (String str : maxPattern.split(" ")) {
res.add(str);
}
return res;
}
}
/***
T: O(nlogn + n^3..)
S: O(n)
name pattern_list
pattern_list_3, count
*/
```
Previous1010. Pairs of Songs With Total Durations Divisible by 60Next1657. Determine if Two Strings Are Close
Last updated