Cloned undirected graph
This commit is contained in:
parent
db38eeada9
commit
9d36627e87
@ -147,3 +147,23 @@ class Node:
|
|||||||
ret += self.left.__list__() if self.left is not None else [None]
|
ret += self.left.__list__() if self.left is not None else [None]
|
||||||
ret += self.next.__list__() if self.next is not None else [None]
|
ret += self.next.__list__() if self.next is not None else [None]
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
class NeighborlyNode:
|
||||||
|
"""NeighborlyNode is a "Node" type used in leetcode graph puzzles"""
|
||||||
|
|
||||||
|
def __init__(self, val=0, neighbors=None):
|
||||||
|
self.val = val
|
||||||
|
self.neighbors = neighbors if neighbors is not None else []
|
||||||
|
|
||||||
|
|
||||||
|
class NeighborlyNodeNicely(typing.NamedTuple):
|
||||||
|
val: int
|
||||||
|
neighbors: list["NeighborlyNodeNicely"]
|
||||||
|
|
||||||
|
def __eq__(self, other: typing.Optional["NeighborlyNodeNicely"]) -> bool:
|
||||||
|
return (
|
||||||
|
other is not None
|
||||||
|
and self.val == other.val
|
||||||
|
and [n.val for n in self.neighbors] == [n.val for n in other.neighbors]
|
||||||
|
)
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
|
import collections.abc
|
||||||
import copy
|
import copy
|
||||||
import itertools
|
|
||||||
import math
|
|
||||||
import random
|
import random
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
@ -581,3 +580,48 @@ def accum_sub_array_maxes(nums: list[int]) -> list[int]:
|
|||||||
accum.append(max(nums[i], prev))
|
accum.append(max(nums[i], prev))
|
||||||
|
|
||||||
return accum
|
return accum
|
||||||
|
|
||||||
|
|
||||||
|
def neighborly_node_from_list(inlist: list[list[int]]):
|
||||||
|
# Alias "Node" type for leetcode compat
|
||||||
|
Node = stdlib.NeighborlyNodeNicely
|
||||||
|
|
||||||
|
if len(inlist) == 0:
|
||||||
|
return None
|
||||||
|
|
||||||
|
outlist = [Node(i + 1, []) for i in range(len(inlist))]
|
||||||
|
|
||||||
|
for i in range(len(inlist)):
|
||||||
|
outlist[i].neighbors[:] = []
|
||||||
|
|
||||||
|
for neighbor_val in inlist[i]:
|
||||||
|
outlist[i].neighbors.append(outlist[neighbor_val - 1])
|
||||||
|
|
||||||
|
return outlist[0]
|
||||||
|
|
||||||
|
|
||||||
|
def neighborly_node_to_list(node) -> list[list[int]]:
|
||||||
|
serialized: dict[int, list[int]] = {}
|
||||||
|
|
||||||
|
for cur in traverse_neighborly_node(node, serialized):
|
||||||
|
if cur is None:
|
||||||
|
break
|
||||||
|
|
||||||
|
serialized[cur.val] = [n.val for n in cur.neighbors]
|
||||||
|
|
||||||
|
return [v for _, v in sorted(serialized.items())]
|
||||||
|
|
||||||
|
|
||||||
|
def traverse_neighborly_node(
|
||||||
|
node: stdlib.NeighborlyNodeNicely, memo: collections.abc.Container[int]
|
||||||
|
) -> typing.Iterator[stdlib.NeighborlyNodeNicely | None]:
|
||||||
|
yield node
|
||||||
|
|
||||||
|
if node is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
for neighbor in node.neighbors:
|
||||||
|
if neighbor.val in memo:
|
||||||
|
continue
|
||||||
|
|
||||||
|
yield from traverse_neighborly_node(neighbor, memo)
|
||||||
|
@ -475,3 +475,19 @@ def test_trie_busy():
|
|||||||
)
|
)
|
||||||
def test_max_sub_array(nums: list[int], expected: int):
|
def test_max_sub_array(nums: list[int], expected: int):
|
||||||
assert stuff.sum_max_sub_array(nums) == expected
|
assert stuff.sum_max_sub_array(nums) == expected
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("inlist",),
|
||||||
|
[
|
||||||
|
([[2, 3, 4], [1, 7], [1], [1, 5, 6, 8], [4], [4], [2], [4]],),
|
||||||
|
([[2, 4], [1, 3], [2, 4], [1, 3]],),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_copy_neighborly_node(inlist):
|
||||||
|
orig = stuff.neighborly_node_from_list(inlist)
|
||||||
|
copied = stuff.neighborly_node_from_list(stuff.neighborly_node_to_list(orig))
|
||||||
|
|
||||||
|
assert id(orig) != id(copied)
|
||||||
|
assert orig == copied
|
||||||
|
assert stuff.neighborly_node_to_list(orig) == stuff.neighborly_node_to_list(copied)
|
||||||
|
Loading…
Reference in New Issue
Block a user