Skip to content

Commit e70684b

Browse files
committed
D. J.:
- Added the leetcode problem and solution for 23, 108, 148 and 427 - Added the implementation of the Quadtree data structure
1 parent 93abe50 commit e70684b

10 files changed

+365
-0
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ This repository contains awesome LeetCode problems and solutions written in Pyth
3939
- [20 Valid Parentheses](https://leetcode.com/problems/valid-parentheses/description/)
4040
- [21 Merge Two Sorted Lists](https://leetcode.com/problems/merge-two-sorted-lists/description/)
4141
- [22 Generate Parentheses](https://leetcode.com/problems/generate-parentheses/description/)
42+
- [23 Merge K Sorted Lists](https://leetcode.com/problems/merge-k-sorted-lists/description/)
4243
- [25 Reverse Nodes in k-Group](https://leetcode.com/problems/reverse-nodes-in-k-group/description/)
4344
- [26 Remove Duplicates from Sorted Array](https://leetcode.com/problems/remove-duplicates-from-sorted-array/description/)
4445
- [27 Remove Element](https://leetcode.com/problems/remove-element/description/)
@@ -82,6 +83,7 @@ This repository contains awesome LeetCode problems and solutions written in Pyth
8283
- [104 Maximum Depth of Binary Tree](https://leetcode.com/problems/maximum-depth-of-binary-tree/description/)
8384
- [105 Construct Binary Tree from Preorder and Inorder Traversal](https://leetcode.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/description/)
8485
- [106 Construct Binary Tree from Inorder and Postorder Traversal](https://leetcode.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/description/)
86+
- [108 Convert Sorted Array to Binary Search Tree](https://leetcode.com/problems/convert-sorted-array-to-binary-search-tree/description/)
8587
- [112 Path Sum](https://leetcode.com/problems/path-sum/description/)
8688
- [114 Flatten Binary Tree to Linked List](https://leetcode.com/problems/flatten-binary-tree-to-linked-list/description/)
8789
- [117 Populating Next Right Pointers in Each Node II](https://leetcode.com/problems/populating-next-right-pointers-in-each-node-ii/description/)
@@ -101,6 +103,7 @@ This repository contains awesome LeetCode problems and solutions written in Pyth
101103
- [138 Copy List with Random Pointer](https://leetcode.com/problems/copy-list-with-random-pointer/description/)
102104
- [141 Linked List Cycle](https://leetcode.com/problems/linked-list-cycle/description/)
103105
- [146 LRU Cache](https://leetcode.com/problems/lru-cache/description/)
106+
- [148 Sort List](https://leetcode.com/problems/sort-list/description/)
104107
- [149 Max Points on a Line](https://leetcode.com/problems/max-points-on-a-line/description/)
105108
- [150 Evaluate Reverse Polish Notation](https://leetcode.com/problems/evaluate-reverse-polish-notation/description/)
106109
- [151 Reverse Words in a String](https://leetcode.com/problems/reverse-words-in-a-string/description/)
@@ -140,6 +143,7 @@ This repository contains awesome LeetCode problems and solutions written in Pyth
140143
- [383 Ransom Note](https://leetcode.com/problems/ransom-note/description/)
141144
- [392 Is Subsequence](https://leetcode.com/problems/is-subsequence/description/)
142145
- [399 Evaluate Division](https://leetcode.com/problems/evaluate-division/description/)
146+
- [427 Construct Quad Tree](https://leetcode.com/problems/construct-quad-tree/description/)
143147
- [433 Minimum Genetic Mutation](https://leetcode.com/problems/minimum-genetic-mutation/description/)
144148
- [452 Minimum Number of Arrows to Burst Balloons](https://leetcode.com/problems/minimum-number-of-arrows-to-burst-balloons/description/)
145149
- [530 Minimum Absolute Difference in BST](https://leetcode.com/problems/minimum-absolute-difference-in-bst/description/)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from typing import List, Optional
2+
3+
from awesome_python_leetcode.tree import TreeNode
4+
5+
6+
class Solution:
7+
"""Base class for all LeetCode Problems."""
8+
9+
def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]:
10+
"""
11+
Given an integer array nums where the elements are sorted in ascending order,
12+
convert it to a height-balanced binary search tree.
13+
"""
14+
if not nums:
15+
return None
16+
mid = len(nums) // 2
17+
node = TreeNode(val=nums[mid])
18+
node.left = self.sortedArrayToBST(nums[:mid])
19+
node.right = self.sortedArrayToBST(nums[mid + 1 :])
20+
return node
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
from typing import Optional
2+
3+
from awesome_python_leetcode.list import ListNode
4+
5+
6+
class Solution:
7+
"""Base class for all LeetCode Problems."""
8+
9+
def merge(self, left: Optional[ListNode], right: Optional[ListNode]):
10+
dummy = ListNode(0)
11+
head = dummy
12+
while left and right:
13+
if left.val < right.val:
14+
head.next = left
15+
left = left.next
16+
else:
17+
head.next = right
18+
right = right.next
19+
head = head.next
20+
if left:
21+
head.next = left
22+
if right:
23+
head.next = right
24+
return dummy.next
25+
26+
def getMid(self, head: Optional[ListNode]) -> Optional[ListNode]:
27+
slow, fast = head, head.next
28+
while fast and fast.next:
29+
slow = slow.next
30+
fast = fast.next.next
31+
return slow
32+
33+
def sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:
34+
"""
35+
Given the head of a linked list, return the list after sorting it in
36+
ascending order.
37+
"""
38+
if not head or not head.next:
39+
return head
40+
41+
# Split list into two halfs
42+
left = head
43+
right = self.getMid(head)
44+
tmp = right.next
45+
right.next = None
46+
right = tmp
47+
48+
# Recursion
49+
left = self.sortList(left)
50+
right = self.sortList(right)
51+
return self.merge(left, right)
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
from typing import List, Optional
2+
3+
from awesome_python_leetcode.list import ListNode
4+
5+
6+
class Solution:
7+
"""Base class for all LeetCode Problems."""
8+
9+
def merge(self, left: Optional[ListNode], right: Optional[ListNode]):
10+
dummy = ListNode(0)
11+
head = dummy
12+
while left and right:
13+
if left.val < right.val:
14+
head.next = left
15+
left = left.next
16+
else:
17+
head.next = right
18+
right = right.next
19+
head = head.next
20+
if left:
21+
head.next = left
22+
if right:
23+
head.next = right
24+
return dummy.next
25+
26+
def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
27+
"""
28+
You are given an array of k linked-lists lists, each linked-list is sorted in
29+
ascending order.
30+
31+
Merge all the linked-lists into one sorted linked-list and return it.
32+
"""
33+
if not lists:
34+
return None
35+
if len(lists) == 1:
36+
return lists[0]
37+
elif len(lists) == 2:
38+
return self.merge(lists[0], lists[1])
39+
else:
40+
mid = len(lists) // 2
41+
left = self.mergeKLists(lists[:mid])
42+
right = self.mergeKLists(lists[mid:])
43+
return self.merge(left, right)
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
from typing import List
2+
3+
from awesome_python_leetcode.tree import QuadTreeNode
4+
5+
6+
class Solution:
7+
"""Base class for all LeetCode Problems."""
8+
9+
def construct(self, grid: List[List[int]]) -> "QuadTreeNode":
10+
"""
11+
Given a n * n matrix grid of 0's and 1's only. We want to represent grid with a
12+
Quad-Tree.
13+
14+
Return the root of the Quad-Tree representing grid.
15+
16+
A Quad-Tree is a tree data structure in which each internal node has exactly
17+
four children. Besides, each node has two attributes:
18+
- val: True if the node represents a grid of 1's or False if the node represents
19+
a grid of 0's. Notice that you can assign the val to True or False when isLeaf
20+
is False, and both are accepted in the answer.
21+
- isLeaf: True if the node is a leaf node on the tree or False if the node has
22+
four children.
23+
class Node {
24+
public boolean val;
25+
public boolean isLeaf;
26+
public Node topLeft;
27+
public Node topRight;
28+
public Node bottomLeft;
29+
public Node bottomRight;
30+
}
31+
32+
We can construct a Quad-Tree from a two-dimensional area using the following
33+
steps:
34+
1. If the current grid has the same value (i.e all 1's or all 0's) set isLeaf
35+
True and set val to the value of the grid and set the four children to Null
36+
and stop.
37+
2. If the current grid has different values, set isLeaf to False and set val to
38+
any value and divide the current grid into four sub-grids as shown in the photo.
39+
3. Recurse for each of the children with the proper sub-grid.
40+
"""
41+
42+
def dfs(n: int, row: int, col: int):
43+
allSame = True
44+
for i in range(n):
45+
for j in range(n):
46+
if grid[row][col] != grid[row + i][col + j]:
47+
allSame = False
48+
break
49+
if allSame:
50+
return QuadTreeNode(grid[row][col], 1)
51+
52+
n = n // 2
53+
topLeft = dfs(n, row, col)
54+
topRight = dfs(n, row, col + n)
55+
bottomLeft = dfs(n, row + n, col)
56+
bottomRight = dfs(n, row + n, col + n)
57+
return QuadTreeNode(0, 0, topLeft, topRight, bottomLeft, bottomRight)
58+
59+
return dfs(len(grid), 0, 0)

awesome_python_leetcode/tree.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,85 @@
11
from typing import List, Optional
22

33

4+
class QuadTreeNode:
5+
"""Quad tree node."""
6+
7+
def __init__(
8+
self,
9+
val: int = 0,
10+
isLeaf: bool = False,
11+
topLeft: Optional["QuadTreeNode"] = None,
12+
topRight: Optional["QuadTreeNode"] = None,
13+
bottomLeft: Optional["QuadTreeNode"] = None,
14+
bottomRight: Optional["QuadTreeNode"] = None,
15+
):
16+
self.val = val
17+
self.isLeaf = isLeaf
18+
self.topLeft = topLeft
19+
self.topRight = topRight
20+
self.bottomLeft = bottomLeft
21+
self.bottomRight = bottomRight
22+
23+
def __eq__(self, other: "QuadTreeNode") -> bool:
24+
if self is None and other is None:
25+
return True
26+
elif self is None:
27+
return False
28+
elif other is None:
29+
return False
30+
else:
31+
return (
32+
self.val == other.val
33+
and self.isLeaf == other.isLeaf
34+
and self.topLeft == other.topLeft
35+
and self.topRight == other.topRight
36+
and self.bottomLeft == other.bottomLeft
37+
and self.bottomRight == other.bottomRight
38+
)
39+
40+
@staticmethod
41+
def build(levelorder: List[List[int]]) -> "QuadTreeNode":
42+
"""Build a binary tree from levelorder traversal."""
43+
if not levelorder:
44+
return None
45+
46+
node_data = levelorder.pop(0)
47+
if node_data is None:
48+
return None
49+
50+
isLeaf, val = node_data
51+
head = QuadTreeNode(val, isLeaf)
52+
queue = [(head, isLeaf)]
53+
54+
while queue and levelorder:
55+
node, isLeaf = queue.pop(0)
56+
57+
node_data = levelorder.pop(0)
58+
if node_data:
59+
isLeaf, val = node_data
60+
node.topLeft = QuadTreeNode(val, isLeaf)
61+
queue.append((node.topLeft, isLeaf))
62+
63+
node_data = levelorder.pop(0)
64+
if node_data:
65+
isLeaf, val = node_data
66+
node.topRight = QuadTreeNode(val, isLeaf)
67+
queue.append((node.topRight, isLeaf))
68+
69+
node_data = levelorder.pop(0)
70+
if node_data:
71+
isLeaf, val = node_data
72+
node.bottomLeft = QuadTreeNode(val, isLeaf)
73+
queue.append((node.bottomLeft, isLeaf))
74+
75+
node_data = levelorder.pop(0)
76+
if node_data:
77+
isLeaf, val = node_data
78+
node.bottomRight = QuadTreeNode(val, isLeaf)
79+
queue.append((node.bottomRight, isLeaf))
80+
return head
81+
82+
483
class TreeNode:
584
"""Binary tree node."""
685

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from typing import List
2+
3+
import pytest
4+
5+
from awesome_python_leetcode._108_convert_sorted_array_to_binary_search_tree import (
6+
Solution,
7+
TreeNode,
8+
)
9+
10+
11+
@pytest.mark.parametrize(
12+
argnames=["nums", "expected"],
13+
argvalues=[
14+
([-10, -3, 0, 5, 9], [0, -3, 9, -10, None, 5]),
15+
([1, 3], [3, 1]),
16+
],
17+
)
18+
def test_func(nums: List[int], expected: List[int]):
19+
"""Tests the solution of a LeetCode problem."""
20+
expected = TreeNode.build(expected)
21+
actual = Solution().sortedArrayToBST(nums)
22+
assert actual == expected

tests/test_148_sort_list.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from typing import List
2+
3+
import pytest
4+
5+
from awesome_python_leetcode._148_sort_list import Solution, ListNode
6+
7+
8+
@pytest.mark.parametrize(
9+
argnames=["head", "expected"],
10+
argvalues=[
11+
([4, 2, 1, 3], [1, 2, 3, 4]),
12+
([-1, 5, 3, 4, 0], [-1, 0, 3, 4, 5]),
13+
([], []),
14+
],
15+
)
16+
def test_func(head: List[int], expected: List[int]):
17+
"""Tests the solution of a LeetCode problem."""
18+
head = ListNode.build(head)
19+
expected = ListNode.build(expected)
20+
actual = Solution().sortList(head)
21+
assert actual == expected

tests/test_23_merge_k_sorted_lists.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from typing import List
2+
3+
import pytest
4+
5+
from awesome_python_leetcode._23_merge_k_sorted_lists import Solution, ListNode
6+
7+
8+
@pytest.mark.parametrize(
9+
argnames=["lists", "expected"],
10+
argvalues=[
11+
([[1, 4, 5], [1, 3, 4], [2, 6]], [1, 1, 2, 3, 4, 4, 5, 6]),
12+
([], []),
13+
([[]], []),
14+
],
15+
)
16+
def test_func(lists: List[List[int]], expected: List[int]):
17+
"""Tests the solution of a LeetCode problem."""
18+
lists = [ListNode.build(sublist) for sublist in lists]
19+
expected = ListNode.build(expected)
20+
actual = Solution().mergeKLists(lists)
21+
assert actual == expected

0 commit comments

Comments
 (0)