{x}
blog image

Subdomain Visit Count

A website domain "discuss.leetcode.com" consists of various subdomains. At the top level, we have "com", at the next level, we have "leetcode.com" and at the lowest level, "discuss.leetcode.com". When we visit a domain like "discuss.leetcode.com", we will also visit the parent domains "leetcode.com" and "com" implicitly.

A count-paired domain is a domain that has one of the two formats "rep d1.d2.d3" or "rep d1.d2" where rep is the number of visits to the domain and d1.d2.d3 is the domain itself.

  • For example, "9001 discuss.leetcode.com" is a count-paired domain that indicates that discuss.leetcode.com was visited 9001 times.

Given an array of count-paired domains cpdomains, return an array of the count-paired domains of each subdomain in the input. You may return the answer in any order.

 

Example 1:

Input: cpdomains = ["9001 discuss.leetcode.com"]
Output: ["9001 leetcode.com","9001 discuss.leetcode.com","9001 com"]
Explanation: We only have one website domain: "discuss.leetcode.com".
As discussed above, the subdomain "leetcode.com" and "com" will also be visited. So they will all be visited 9001 times.

Example 2:

Input: cpdomains = ["900 google.mail.com", "50 yahoo.com", "1 intel.mail.com", "5 wiki.org"]
Output: ["901 mail.com","50 yahoo.com","900 google.mail.com","5 wiki.org","5 org","1 intel.mail.com","951 com"]
Explanation: We will visit "google.mail.com" 900 times, "yahoo.com" 50 times, "intel.mail.com" once and "wiki.org" 5 times.
For the subdomains, we will visit "mail.com" 900 + 1 = 901 times, "com" 900 + 50 + 1 = 951 times, and "org" 5 times.

 

Constraints:

  • 1 <= cpdomain.length <= 100
  • 1 <= cpdomain[i].length <= 100
  • cpdomain[i] follows either the "repi d1i.d2i.d3i" format or the "repi d1i.d2i" format.
  • repi is an integer in the range [1, 104].
  • d1i, d2i, and d3i consist of lowercase English letters.

Solution Explanation

This problem involves processing a list of count-paired domains and returning a list of all subdomains and their visit counts. The solution uses a hash map (dictionary in Python) to efficiently store and count subdomain visits.

Approach:

  1. Initialization: A hash map (or dictionary) is created to store subdomains as keys and their visit counts as values.

  2. Iterating through Count-Paired Domains: The code iterates through each cpdomain string in the input list.

  3. Parsing the Count and Domain: For each cpdomain, the code splits it into the visit count (an integer) and the domain name.

  4. Subdomain Generation and Counting: The code then iterates through the domain name, splitting it at each dot (.) to generate all subdomains. For example, "discuss.leetcode.com" would generate "discuss.leetcode.com", "leetcode.com", and "com". Each generated subdomain is added to the hash map, and its count is incremented by the visit count obtained in step 3.

  5. Result Formatting: Finally, the code iterates through the hash map and creates a list of strings in the format "count subdomain" and returns this list.

Time Complexity Analysis:

  • The outer loop iterates through the cpdomains list, which has a length of n.
  • The inner loop iterates through the characters of each domain name, which has a maximum length of m. In the worst case, the domain name could be a single, long subdomain. The number of subdomains generated is at most the length of the domain string.
  • The operations within the loops (string manipulation, hash map lookups, and insertions) take constant time O(1).

Therefore, the overall time complexity is O(n*m), where n is the number of count-paired domains and m is the maximum length of a domain name.

Space Complexity Analysis:

  • The space complexity is dominated by the hash map used to store subdomains and their counts. In the worst-case scenario, the number of subdomains could be proportional to the total number of characters in all domain names.
  • Therefore, the space complexity is O(n*m) in the worst case, where n is the number of count-paired domains and m is the maximum length of a domain name. However, in practice this space may be considerably less as many subdomains will share common suffixes.

Code Examples (with explanations inline):

Python:

from collections import Counter
 
class Solution:
    def subdomainVisits(self, cpdomains: List[str]) -> List[str]:
        cnt = Counter() # Use Counter for efficient counting
        for domain in cpdomains:
            count, domain_str = domain.split()  # Split into count and domain
            count = int(count)                  # Convert count to integer
            subdomains = domain_str.split('.')  # Split domain into subdomains
            for i in range(len(subdomains)):
                subdomain = ".".join(subdomains[i:]) # Reconstruct subdomains
                cnt[subdomain] += count             # Increment count for each subdomain
 
        result = [f"{count} {subdomain}" for subdomain, count in cnt.items()] # Format result
        return result

Java:

import java.util.*;
class Solution {
    public List<String> subdomainVisits(String[] cpdomains) {
        Map<String, Integer> countMap = new HashMap<>(); //Use HashMap for efficient counting
        for (String domain : cpdomains) {
            String[] parts = domain.split("\\s+"); //Split into count and domain using regex for whitespace
            int count = Integer.parseInt(parts[0]);   //Convert count to integer
            String[] subdomains = parts[1].split("\\."); // Split domain into subdomains using regex for dot
 
            for (int i = 0; i < subdomains.length; i++) {
                StringBuilder sb = new StringBuilder();
                for (int j = i; j < subdomains.length; j++) {
                    sb.append(subdomains[j]);
                    if (j < subdomains.length -1) sb.append("."); // Add dot if not last subdomain
                }
                String subdomain = sb.toString();
                countMap.put(subdomain, countMap.getOrDefault(subdomain, 0) + count); //Increment count
            }
        }
 
        List<String> result = new ArrayList<>();
        for (Map.Entry<String, Integer> entry : countMap.entrySet()) {
            result.add(entry.getValue() + " " + entry.getKey()); // Format result
        }
        return result;
    }
}

The other languages (C++, Go) would follow a very similar structure using their respective hash map implementations and string manipulation functions. The core logic remains the same across all languages.