[LeetCode] 1152. Analyze User Website Visit Pattern
You are given two string arrays username
and website
and an integer array timestamp
. All the given arrays are of the same length and the tuple [username[i], website[i], timestamp[i]]
indicates that the user username[i]
visited the website website[i]
at time timestamp[i]
.
A pattern is a list of three websites (not necessarily distinct).
- For example,
["home", "away", "love"]
,["leetcode", "love", "leetcode"]
, and["luffy", "luffy", "luffy"]
are all patterns.
The score of a pattern is the number of users that visited all the websites in the pattern in the same order they appeared in the pattern.
- For example, if the pattern is
["home", "away", "love"]
, the score is the number of usersx
such thatx
visited"home"
then visited"away"
and visited"love"
after that. - Similarly, if the pattern is
["leetcode", "love", "leetcode"]
, the score is the number of usersx
such thatx
visited"leetcode"
then visited"love"
and visited"leetcode"
one more time after that. - Also, if the pattern is
["luffy", "luffy", "luffy"]
, the score is the number of usersx
such thatx
visited"luffy"
three different times at different timestamps.
Return the pattern with the largest score. If there is more than one pattern with the same largest score, return the lexicographically smallest such pattern.
Example 1:
Input: username = ["joe","joe","joe","james","james","james","james","mary","mary","mary"], timestamp = [1,2,3,4,5,6,7,8,9,10], website = ["home","about","career","home","cart","maps","home","home","about","career"] Output: ["home","about","career"] Explanation: The tuples in this example are: ["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]. The pattern ("home", "about", "career") has score 2 (joe and mary). The pattern ("home", "cart", "maps") has score 1 (james). The pattern ("home", "cart", "home") has score 1 (james). The pattern ("home", "maps", "home") has score 1 (james). The pattern ("cart", "maps", "home") has score 1 (james). The pattern ("home", "home", "home") has score 0 (no user visited home 3 times).
Example 2:
Input: username = ["ua","ua","ua","ub","ub","ub"], timestamp = [1,2,3,4,5,6], website = ["a","b","a","a","b","c"] Output: ["a","b","a"]
Constraints:
3 <= username.length <= 50
1 <= username[i].length <= 10
timestamp.length == username.length
1 <= timestamp[i] <= 109
website.length == username.length
1 <= website[i].length <= 10
username[i]
andwebsite[i]
consist of lowercase English letters.- It is guaranteed that there is at least one user who visited at least three websites.
- All the tuples
[username[i], timestamp[i], website[i]]
are unique.
用户网站访问行为分析。
给定两个字符串数组 username 和 website 和一个整数数组 timestamp 。给定的数组长度相同,其中元组 [username[i], website[i], timestamp[i]] 表示用户 username[i] 在时间 timestamp[i] 访问了网站 website[i] 。
访问模式 是包含三个网站的列表(不一定是完全不同的)。
例如,["home", "away", "love"], ["leetcode", "love", "leetcode"],和 ["luffy", "luffy", "luffy"] 都是模式。
一种 访问模式 的 得分 是访问该模式中所有网站的用户数量,这些网站在该模式中出现的顺序相同。例如,如果模式是 [“home”,“away”,“love”] ,那么分数就是用户数量 x , x 访问了 “home” ,然后访问了 “away” ,然后访问了 “love” 。
同样,如果模式是 ["leetcode", "love", "leetcode"] ,那么分数就是用户数量 x ,使得 x 访问了"leetcode",然后访问了 "love" ,之后又访问了 "leetcode" 。
另外,如果模式是 [“luffy”,“luffy”,“luffy”] ,那么分数就是用户数量 x ,这样 x 就可以在不同的时间戳上访问 “luffy” 三次。
返回 得分 最大的 访问模式 。如果有多个访问模式具有相同的最大分数,则返回字典序最小的。来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/analyze-user-website-visit-pattern
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
这道题不涉及算法,算是实现题。题目给了三个数组,分别表示用户名,网站名称和时间戳。我们需要返回的是一个访问次数最多的模式 pattern。模式的定义是哪个访问路径最多,这个路径就是模式。题目给的三个数组是等长的,所以当我们访问到 timestamp[i] 的时候,timestamp[i], username[i] 和 website[i] 分别表示在某个时间点,某个用户访问了某个网站。
Java 做这道题还是稍微有点麻烦的,这里我创建了一个 Pair类 存放时间戳和网站名称,一个 hashmap1 存放<username, Pair<timestamp, website>>。
第一次遍历,我把所有的访问记录存在了 hashmap1 里面。
这里我再遍历 hashmap1 里所有的 key(username),同时我需要另一个 hashmap2 记录<website, count>。对于每个 unique 的用户,我从 hashmap1 里获得TA的访问记录,用一个 list 存好,并且按时间戳排序,这样对于同一个用户,访问时间在前的网站名称会在前。这也是符合正常的访问顺序的。对于我从 hashmap1 里拿出来的访问轨迹(网站A-网站B-网站C),我开始把他拼接成一个字符串,然后看看每个不同的访问轨迹出现了多少次,最后留下出现次数最多的那个访问轨迹。
此时这个轨迹还是一个字符串,我们最后把他再改回 list 的形式之后再返回。
时间O(nlogn)
空间O(n)
Java实现
1 class Solution { 2 public List<String> mostVisitedPattern(String[] username, int[] timestamp, String[] website) { 3 HashMap<String, List<Pair>> map = new HashMap<>(); 4 int len = username.length; 5 // collect the website info for every user, key: username, value: (timestamp, website) 6 for (int i = 0; i < len; i++) { 7 map.putIfAbsent(username[i], new ArrayList<>()); 8 map.get(username[i]).add(new Pair(timestamp[i], website[i])); 9 } 10 11 // count map 12 HashMap<String, Integer> count = new HashMap<>(); 13 String res = ""; 14 for (String key : map.keySet()) { 15 HashSet<String> set = new HashSet<>(); 16 List<Pair> list = map.get(key); 17 // 时间早的在前,这也符合访问顺序 18 Collections.sort(list, (a, b) -> a.time - b.time); 19 for (int i = 0; i < list.size(); i++) { 20 for (int j = i + 1; j < list.size(); j++) { 21 for (int k = j + 1; k < list.size(); k++) { 22 String str = list.get(i).web + " " + list.get(j).web + " " + list.get(k).web; 23 if (!set.contains(str)) { 24 count.put(str, count.getOrDefault(str, 0) + 1); 25 set.add(str); 26 } 27 if (res.equals("") || count.get(res) < count.get(str) || (count.get(res) == count.get(str) && res.compareTo(str) > 0)) { 28 res = str; 29 } 30 } 31 } 32 } 33 } 34 35 // 再把字符串改回list 36 String[] p = res.split(" "); 37 List<String> path = new ArrayList<>(); 38 for (String site : p) { 39 path.add(site); 40 } 41 return path; 42 } 43 } 44 45 class Pair { 46 int time; 47 String web; 48 public Pair(int time, String web) { 49 this.time = time; 50 this.web = web; 51 } 52 }