Skip to main content

Command Palette

Search for a command to run...

Solving Leetcode Interviews in Seconds with AI: Count Ways to Build Rooms in an Ant Colony

Updated
4 min read

Introduction

In this blog post, we will explore how to solve the LeetCode problem "1916" using AI. LeetCode is a popular platform for preparing for coding interviews, and with the help of AI tools like Chatmagic, we can generate solutions quickly and efficiently - helping you pass the interviews and get the job offer without having to study for months.

Problem Statement

You are an ant tasked with adding n new rooms numbered 0 to n-1 to your colony. You are given the expansion plan as a 0-indexed integer array of length n, prevRoom, where prevRoom[i] indicates that you must build room prevRoom[i] before building room i, and these two rooms must be connected directly. Room 0 is already built, so prevRoom[0] = -1. The expansion plan is given such that once all the rooms are built, every room will be reachable from room 0. You can only build one room at a time, and you can travel freely between rooms you have already built only if they are connected. You can choose to build any room as long as its previous room is already built. Return the number of different orders you can build all the rooms in. Since the answer may be large, return it modulo 109 + 7. Example 1:
Input: prevRoom = [-1,0,1] Output: 1 Explanation: There is only one way to build the additional rooms: 0 → 1 → 2 Example 2:
Input: prevRoom = [-1,0,0,1,2] Output: 6 Explanation: The 6 ways are: 0 → 1 → 3 → 2 → 4 0 → 2 → 4 → 1 → 3 0 → 1 → 2 → 3 → 4 0 → 1 → 2 → 4 → 3 0 → 2 → 1 → 3 → 4 0 → 2 → 1 → 4 → 3 Constraints: n == prevRoom.length 2 <= n <= 105 prevRoom[0] == -1 0 <= prevRoom[i] < n for all 1 <= i < n Every room is reachable from room 0 once all the rooms are built.

Explanation

Here's the breakdown of the solution, followed by the Python code:

  • Topological Sort with DFS & Combinatorics: The problem boils down to figuring out the possible building orders given dependencies. We model the dependencies as a tree. Then, we treat each subtree as a "block" to be inserted into the build order. Within each subtree, we need to count the number of possible permutations. This can be solved by considering the size of each subtree and using combinatorics.
  • Subtree Size and Factorials: We perform a DFS to calculate the size of each subtree (number of nodes in the subtree). We precompute factorials and their inverses (modulo 10^9 + 7) to efficiently compute binomial coefficients during the DFS traversal.
  • Modular Arithmetic: All calculations are done modulo 10^9 + 7 to prevent overflow.

  • Runtime Complexity: O(n log n), primarily due to modular inverse calculations (using exponentiation by squaring).

  • Storage Complexity: O(n) for storing factorials, inverse factorials, subtree sizes, and the adjacency list representing the room dependencies.

Code

    def countOrders(prevRoom):
    n = len(prevRoom)
    adj = [[] for _ in range(n)]
    for i in range(1, n):
        adj[prevRoom[i]].append(i)

    subtree_size = [0] * n
    fact = [1] * (n + 1)
    inv_fact = [1] * (n + 1)
    mod = 10**9 + 7

    def power(a, b, m):
        res = 1
        a %= m
        while b > 0:
            if b % 2 == 1:
                res = (res * a) % m
            a = (a * a) % m
            b //= 2
        return res

    def modInverse(n, m):
        return power(n, m - 2, m)

    for i in range(2, n + 1):
        fact[i] = (fact[i - 1] * i) % mod
    inv_fact[n] = modInverse(fact[n], mod)
    for i in range(n - 1, 1, -1):
        inv_fact[i] = (inv_fact[i + 1] * (i + 1)) % mod

    def combinations(n, k, m):
        if k < 0 or k > n:
            return 0
        num = fact[n]
        den = (inv_fact[k] * inv_fact[n - k]) % m
        return (num * den) % m

    ans = 1

    def dfs(node):
        nonlocal ans
        subtree_size[node] = 1
        ways = 1
        total_size = 0

        for child in adj[node]:
            dfs(child)
            ways = (ways * subtree_size[child]) % mod
            ways = (ways * ans) % mod  # Accumulate ans from children
            total_size += subtree_size[child]

        ans = combinations(total_size, subtree_size[adj[node][0] if adj[node] else 0] , mod) if adj[node] else 1

        for i in range (1,len(adj[node])):
            ans = (ans * combinations(total_size - sum(subtree_size[adj[node][j]] for j in range(i)), subtree_size[adj[node][i]],mod))%mod

        subtree_size[node] = total_size + 1
        return

    dfs(0)
    return ans

More from this blog

C

Chatmagic blog

2894 posts