Skip to main content

Command Palette

Search for a command to run...

Solving Leetcode Interviews in Seconds with AI: Process Restricted Friend Requests

Updated
4 min read

Introduction

In this blog post, we will explore how to solve the LeetCode problem "2076" 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 given an integer n indicating the number of people in a network. Each person is labeled from 0 to n - 1. You are also given a 0-indexed 2D integer array restrictions, where restrictions[i] = [xi, yi] means that person xi and person yi cannot become friends, either directly or indirectly through other people. Initially, no one is friends with each other. You are given a list of friend requests as a 0-indexed 2D integer array requests, where requests[j] = [uj, vj] is a friend request between person uj and person vj. A friend request is successful if uj and vj can be friends. Each friend request is processed in the given order (i.e., requests[j] occurs before requests[j + 1]), and upon a successful request, uj and vj become direct friends for all future friend requests. Return a boolean array result, where each result[j] is true if the jth friend request is successful or false if it is not. Note: If uj and vj are already direct friends, the request is still successful. Example 1: Input: n = 3, restrictions = [[0,1]], requests = [[0,2],[2,1]] Output: [true,false] Explanation: Request 0: Person 0 and person 2 can be friends, so they become direct friends. Request 1: Person 2 and person 1 cannot be friends since person 0 and person 1 would be indirect friends (1--2--0). Example 2: Input: n = 3, restrictions = [[0,1]], requests = [[1,2],[0,2]] Output: [true,false] Explanation: Request 0: Person 1 and person 2 can be friends, so they become direct friends. Request 1: Person 0 and person 2 cannot be friends since person 0 and person 1 would be indirect friends (0--2--1). Example 3: Input: n = 5, restrictions = [[0,1],[1,2],[2,3]], requests = [[0,4],[1,2],[3,1],[3,4]] Output: [true,false,true,false] Explanation: Request 0: Person 0 and person 4 can be friends, so they become direct friends. Request 1: Person 1 and person 2 cannot be friends since they are directly restricted. Request 2: Person 3 and person 1 can be friends, so they become direct friends. Request 3: Person 3 and person 4 cannot be friends since person 0 and person 1 would be indirect friends (0--4--3--1). Constraints: 2 <= n <= 1000 0 <= restrictions.length <= 1000 restrictions[i].length == 2 0 <= xi, yi <= n - 1 xi != yi 1 <= requests.length <= 1000 requests[j].length == 2 0 <= uj, vj <= n - 1 uj != vj

Explanation

Here's a breakdown of the solution:

  • Disjoint Set Union (DSU): Use DSU to track connected components (friend groups). Initially, each person is in their own component.
  • Check Restrictions: Before uniting two people in a request, check if uniting them would violate any restrictions. This involves finding the root of each person in the request and, if they are different, temporarily uniting them to check for restriction violations. If no violation is found, permanently unite them.
  • Result Array: Maintain a boolean array to store the success status of each friend request.

  • Runtime Complexity: O(m * (n + r * α(n))), where m is the number of requests, n is the number of people, r is the number of restrictions, and α(n) is the inverse Ackermann function (effectively constant for practical input sizes). Storage Complexity: O(n)

Code

    class DSU:
    def __init__(self, n):
        self.parent = list(range(n))
        self.rank = [0] * n

    def find(self, x):
        if self.parent[x] != x:
            self.parent[x] = self.find(self.parent[x])  # Path compression
        return self.parent[x]

    def union(self, x, y):
        root_x = self.find(x)
        root_y = self.find(y)
        if root_x != root_y:
            if self.rank[root_x] < self.rank[root_y]:
                self.parent[root_x] = root_y
            elif self.rank[root_x] > self.rank[root_y]:
                self.parent[root_y] = root_x
            else:
                self.parent[root_y] = root_x
                self.rank[root_x] += 1
            return True
        return False  # Already in the same set


def friend_requests(n: int, restrictions: list[list[int]], requests: list[list[int]]) -> list[bool]:
    dsu = DSU(n)
    result = []
    for u, v in requests:
        root_u = dsu.find(u)
        root_v = dsu.find(v)

        can_friend = True
        if root_u != root_v:

            temp_parent_u = dsu.parent[u]
            temp_parent_v = dsu.parent[v]
            temp_rank = dsu.rank[:]


            dsu.union(u,v)

            for x, y in restrictions:
                root_x = dsu.find(x)
                root_y = dsu.find(y)
                if root_x == root_y:
                    can_friend = False
                    break

            if can_friend:
                result.append(True)
            else:

                dsu.parent = list(range(n))
                dsu = DSU(n)
                for i in range(n):
                  dsu.parent[i] = i


                new_dsu = DSU(n)
                for i in range(n):
                  new_dsu.parent[i] = dsu.parent[i]

                for res in requests:
                  if res == [u,v]:
                    break

                  if new_dsu.find(res[0]) != new_dsu.find(res[1]):

                    new_dsu.union(res[0],res[1])

                dsu = new_dsu

                result.append(False)
        else:
          result.append(True)

    return result

More from this blog

C

Chatmagic blog

2894 posts