diff --git a/Problem1.py b/Problem1.py new file mode 100644 index 0000000..9881800 --- /dev/null +++ b/Problem1.py @@ -0,0 +1,22 @@ +# Problem1 Find Judge (https://leetcode.com/problems/find-the-town-judge/) +# Time Complexity: O(n + t),We loop through the trust list once (t edges), then loop through all n people once. +# Space Complexity: O(n),We store an indegrees array of size n+1. +# Approach: +# The town judge is trusted by everyone else but trusts nobody. +# For each trust pair [a, b], a trusts b, so we decrease a's score (a trusts someone, so a cannot be the judge) +# and increase b's score (b is trusted by someone). +# The judge is the one person whose final score equals n-1, meaning everyone else trusts them and they trust no one. + +class Solution: + def findJudge(self, n: int, trust: List[List[int]]) -> int: + indegrees = [0] * (n + 1) # score for each person from 1 to n, index 0 is unused + + for i in trust: # go through each trust pair + indegrees[i[0]] -= 1 # person i[0] trusts someone, so they lose a point (cannot be judge if they trust anyone) + indegrees[i[1]] += 1 # person i[1]] is trusted by someone, so they gain a point + + for i in range(1, n + 1): # check every person from 1 to n + if indegrees[i] == n - 1: # trusted by everyone else and trusts nobody + return i # found the judge + + return -1 # no one matches, no judge exists \ No newline at end of file diff --git a/Problem2.py b/Problem2.py new file mode 100644 index 0000000..408ff74 --- /dev/null +++ b/Problem2.py @@ -0,0 +1,46 @@ +# Problem2 The Maze (https://leetcode.com/problems/the-maze/) +# Time Complexity: O(m * n * max(m, n)),Each cell can be visited once as a "stopping point" -> O(m*n) DFS calls.From each stopping point, we roll in 4 directions, each roll can take up to O(max(m,n)) steps +# Space Complexity: O(m * n),Recursion stack in the worst case can hold O(m*n) calls(the maze itself is reused as the visited array, so no extra visited grid is needed) +# Approach: +# The ball doesn't stop cell by cell, it rolls until it hits a wall or the border. +# So from each position, roll in all 4 directions until blocked, and only stop there. +# Treat each "stopping point" as a node, and DFS between stopping points. +# Mark visited stopping points as -1 in the maze to avoid revisiting the same paths. + +class Solution: + def hasPath(self, maze, start, destination): + self.dirs = [(1,0),(0,1),(0,-1),(-1,0)] # down, right, left, up + self.m = len(maze) # number of rows + self.n = len(maze[0]) # number of columns + + return self.dfs(maze, start[0], start[1], destination) + + def dfs(self, maze, i, j, destination): + # base case 1: reached the destination + if destination[0] == i and destination[1] == j: + return True + + # base case 2: already visited this stopping point, avoid infinite loop + if maze[i][j] == -1: + return False + + maze[i][j] = -1 # mark current stopping point as visited + + for dir in self.dirs: + r = dir[0] + i # take one step in this direction + c = dir[1] + j + + # keep rolling while still inside the maze and not hitting a wall + while r >= 0 and c >= 0 and r < self.m and c < self.n and maze[r][c] != 1: + r += dir[0] + c += dir[1] + + # the loop above overshoots by one step (lands on wall/border), so step back + r -= dir[0] + c -= dir[1] + + # recursively check if the destination is reachable from this new stopping point + if self.dfs(maze, r, c, destination): + return True + + return False # no direction led to the destination \ No newline at end of file