@@ -1590,3 +1590,69 @@ def exclusiveTime(self, n: int, logs: List[str]) -> List[int]:
15901590
15911591 return res
15921592
1593+ ############# 249. Group Shifted Strings #############
1594+ class Solution :
1595+ def groupStrings (self , strings : List [str ]) -> List [List [str ]]:
1596+ hashmap = defaultdict (list )
1597+ for s in strings :
1598+ key = []
1599+ for i in range (len (s ) - 1 ):
1600+ # Throw in 26 so that we can normalzie below
1601+ difference = 26 + ord (s [i + 1 ]) - ord (s [i ])
1602+ # Wrap around
1603+ # z + 1 = a
1604+ key .append (str (difference % 26 ))
1605+ hashmap [',' .join (key )].append (s )
1606+ return list (hashmap .values ())
1607+
1608+
1609+ ############# 317. Shortest Distance from All Buildings #############
1610+ EMPTY , BUILDING , OBSTACLE = 0 , 1 , 2
1611+ DIR = {(0 ,- 1 ), (- 1 ,0 ), (0 ,1 ), (1 ,0 )}
1612+
1613+ class Solution :
1614+
1615+ def shortestDistance (self , grid : List [List [int ]]) -> int :
1616+ buildings = []
1617+ candidate_lands = {} # {position, distance}
1618+
1619+ # 1. Find all buildings and candidate empty lands
1620+ for r in range (len (grid )):
1621+ for c in range (len (grid [r ])):
1622+ if grid [r ][c ] == BUILDING :
1623+ buildings .append ((r , c ))
1624+
1625+ elif grid [r ][c ] == EMPTY :
1626+ candidate_lands [(r , c )] = 0
1627+
1628+ # 2. Compute min distance from each building to all candidate empty lands
1629+ for building_position in buildings :
1630+ self .compute_shortest_distances_bfs (candidate_lands , building_position )
1631+
1632+ return min (candidate_lands .values ()) if buildings and candidate_lands else - 1
1633+
1634+ def compute_shortest_distances_bfs (self , candidate_lands : dict , position : (int , int )):
1635+ """
1636+
1637+ """
1638+ distance = 0
1639+ visited = set ()
1640+
1641+ queue = deque ([position ])
1642+ while queue :
1643+ distance += 1
1644+
1645+ for i in range (len (queue )):
1646+ x , y = queue .popleft ()
1647+ for dx , dy in DIR :
1648+ nx , ny = x + dx , y + dy
1649+
1650+ if (nx , ny ) in candidate_lands and (nx , ny ) not in visited :
1651+ visited .add ((nx , ny ))
1652+ candidate_lands [(nx , ny )] += distance
1653+ queue .append ((nx , ny ))
1654+
1655+ # 2. (Optimization, pruning) All empty lands that are not reachable from a building are excluded
1656+ if len (visited ) != len (candidate_lands ):
1657+ for position in set (candidate_lands .keys ()).difference (visited ):
1658+ candidate_lands .pop (position )
0 commit comments