diff --git a/Exercise_1.py b/Exercise_1.py new file mode 100644 index 0000000..e79c70d --- /dev/null +++ b/Exercise_1.py @@ -0,0 +1,47 @@ +# S30 Problem #216 Optimize Water Distribution in a Village +#LeetCode #1168 https://leetcode.com/problems/optimize-water-distribution-in-a-village/ + +# Author : Akaash Trivedi +# Did this code successfully run on Leetcode : Yes # +# Any problem you faced while coding this : No + +# union find technique +# connect the village node to a dummy node 0 with cost of wells as edge +# add pipe to edges and sort them according to cost +# use union find to connect each nodes until all nodes are connected and return result +# TC: O(E log E) Here E = edges +# SC: O(E + V) +class Solution: + def minCostToSupplyWater(self, n: int, wells: List[int], pipes: List[List[int]]) -> int: + edges = [] + uf = [] # union find + for i in range(n+1): + uf.append(i) + # make a dummy node 0 and draw edges from it to each node and give well cost + for i in range(1,n+1): + # edge from 0 to, node, cost of well + edges.append((0, i, wells[i-1])) + + # add pipes cost to edges + edges.extend(pipes) + edges.sort(key=lambda x:x[2]) + print(edges) + + res = 0 + for edge in edges: + x, y = edge[0], edge[1] + px = self.find(uf, x) # parent x + py = self.find(uf, y) # parent y + + if px != py: + res += edge[2] + uf[py] = px + + return res + + # function to find ulimate parent + def find(self, uf, x): + # base + if x != uf[x]: + uf[x] = self.find(uf, uf[x]) + return uf[x] \ No newline at end of file diff --git a/Exercise_2.py b/Exercise_2.py new file mode 100644 index 0000000..dafedfd --- /dev/null +++ b/Exercise_2.py @@ -0,0 +1,84 @@ +# S30 Problem #194 find celebrity +#LeetCode #277 https://leetcode.com/problems/find-the-celebrity/description/ + +# Author : Akaash Trivedi +# Did this code successfully run on Leetcode : Yes # +# Any problem you faced while coding this : No + +# The knows API is already defined for you. +# return a bool, whether a knows b +# def knows(a: int, b: int) -> bool: + +# topological sort +# indegrees array: (a,b) a knows b +# increase the indegree of person b and degreees indegree of person a +# Person whos indegree is n-1, meaning that everyone knows that person => celebrity +# TC: O(n^2) +# SC: O(n) +class Solution: + def findCelebrity(self, n: int) -> int: + indegree = [0] * n + + for i in range(n): + for j in range(n): + if i == j: continue + if knows(i, j): + # increase the j's indegree and decrease i's + indegree[j] += 1 + indegree[i] -= 1 + + # anyone has indegree n-1, means everyone knows that person + for i in range(n): + if indegree[i] == n - 1: + return i + + return -1 + + +# linear 3n solution +# Assume one of them is a celeb, and update the celeb when they knows someone +# after 1st pass, we found some celeb: check if everyone knows celeb; celeb knows no one +# return the celeb, if not return -1 +# TC: O(n) +# SC: O(1) + +class Solution: + def findCelebrity(self, n: int) -> int: + celeb = 0 # assume starting with 0 is celebrity + for i in range(1, n): + if knows(celeb, i): + # celebrity cant know anyone, move the celebrity to i + celeb = i + + # celeberity should not know anyone and everyone should know celeb + for i in range(n): + if i == celeb:continue + if not knows(i, celeb) or knows(celeb, i): + return -1 + + return celeb + + +# linear 3n solution - little faster +# Assume one of them is a celeb, and update the celeb when they knows someone +# after 1st pass, we found some celeb: check if everyone knows celeb; celeb knows no one +# return the celeb, if not return -1 +# TC: O(n) +# SC: O(1) + +class Solution: + def findCelebrity(self, n: int) -> int: + celeb = 0 # assume starting with 0 is celebrity + for i in range(1, n): + if knows(celeb, i): + # celebrity cant know anyone, move the celebrity to i + celeb = i + + # celeberity should not know anyone and everyone should know celeb + for i in range(n): + if i == celeb:continue + if not knows(i, celeb): + return -1 + if i < celeb and knows(celeb, i): + return -1 + return celeb