Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions .templates/leetcode/json/binary_tree_right_side_view.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"problem_name": "binary_tree_right_side_view",
"solution_class_name": "Solution",
"problem_number": "199",
"problem_title": "Binary Tree Right Side View",
"difficulty": "Medium",
"topics": "Tree, Depth-First Search, Breadth-First Search, Binary Tree",
"tags": ["grind-75"],
"readme_description": "Given the `root` of a binary tree, imagine yourself standing on the **right side** of it, return *the values of the nodes you can see ordered from top to bottom*.",
"readme_examples": [
{
"content": "![Example 1](https://assets.leetcode.com/uploads/2024/11/24/tmpd5jn43fs-1.png)\n\n```\nInput: root = [1,2,3,null,5,null,4]\nOutput: [1,3,4]\n```"
},
{
"content": "![Example 2](https://assets.leetcode.com/uploads/2024/11/24/tmpkpe40xeh-1.png)\n\n```\nInput: root = [1,2,3,4,null,null,null,5]\nOutput: [1,3,4,5]\n```"
},
{ "content": "```\nInput: root = [1,null,3]\nOutput: [1,3]\n```" },
{ "content": "```\nInput: root = []\nOutput: []\n```" }
],
"readme_constraints": "- The number of nodes in the tree is in the range `[0, 100]`.\n- `-100 <= Node.val <= 100`",
"readme_additional": "",
"solution_imports": "from leetcode_py import TreeNode",
"solution_methods": [
{
"name": "right_side_view",
"parameters": "root: TreeNode[int] | None",
"return_type": "list[int]",
"dummy_return": "[]"
}
],
"test_imports": "import pytest\nfrom leetcode_py.test_utils import logged_test\nfrom leetcode_py import TreeNode\nfrom .solution import Solution",
"test_class_name": "BinaryTreeRightSideView",
"test_helper_methods": [
{ "name": "setup_method", "parameters": "", "body": "self.solution = Solution()" }
],
"test_methods": [
{
"name": "test_right_side_view",
"parametrize": "root_list, expected",
"parametrize_typed": "root_list: list[int | None], expected: list[int]",
"test_cases": "[([1, 2, 3, None, 5, None, 4], [1, 3, 4]), ([1, 2, 3, 4, None, None, None, 5], [1, 3, 4, 5]), ([1, None, 3], [1, 3]), ([], [])]",
"body": "root = TreeNode.from_list(root_list)\nresult = self.solution.right_side_view(root)\nassert result == expected"
}
],
"playground_imports": "from solution import Solution\nfrom leetcode_py import TreeNode",
"playground_test_case": "# Example test case\nroot_list: list[int | None] = [1, 2, 3, None, 5, None, 4]\nexpected = [1, 3, 4]",
"playground_execution": "root = TreeNode.from_list(root_list)\nresult = Solution().right_side_view(root)\nresult",
"playground_assertion": "assert result == expected"
}
50 changes: 50 additions & 0 deletions .templates/leetcode/json/clone_graph.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"problem_name": "clone_graph",
"solution_class_name": "Solution",
"problem_number": "133",
"problem_title": "Clone Graph",
"difficulty": "Medium",
"topics": "Hash Table, Depth-First Search, Breadth-First Search, Graph",
"tags": ["grind-75"],
"readme_description": "Given a reference of a node in a **connected** undirected graph.\n\nReturn a **deep copy** (clone) of the graph.\n\nEach node in the graph contains a value (`int`) and a list (`List[Node]`) of its neighbors.\n\n```\nclass Node {\n public int val;\n public List<Node> neighbors;\n}\n```\n\n**Test case format:**\n\nFor simplicity, each node's value is the same as the node's index (1-indexed). For example, the first node with `val == 1`, the second node with `val == 2`, and so on. The graph is represented in the test case using an adjacency list.\n\n**An adjacency list** is a collection of unordered **lists** used to represent a finite graph. Each list describes the set of neighbors of a node in the graph.\n\nThe given node will always be the first node with `val = 1`. You must return the **copy of the given node** as a reference to the cloned graph.",
"readme_examples": [
{
"content": "<img alt=\"\" src=\"https://assets.leetcode.com/uploads/2019/11/04/133_clone_graph_question.png\" style=\"width: 454px; height: 500px;\" />\n\n```\nInput: adjList = [[2,4],[1,3],[2,4],[1,3]]\nOutput: [[2,4],[1,3],[2,4],[1,3]]\nExplanation: There are 4 nodes in the graph.\n1st node (val = 1)'s neighbors are 2nd node (val = 2) and 4th node (val = 4).\n2nd node (val = 2)'s neighbors are 1st node (val = 1) and 3rd node (val = 3).\n3rd node (val = 3)'s neighbors are 2nd node (val = 2) and 4th node (val = 4).\n4th node (val = 4)'s neighbors are 1st node (val = 1) and 3rd node (val = 3).\n```"
},
{
"content": "<img alt=\"\" src=\"https://assets.leetcode.com/uploads/2020/01/07/graph.png\" style=\"width: 163px; height: 148px;\" />\n\n```\nInput: adjList = [[]]\nOutput: [[]]\nExplanation: Note that the input contains one empty list. The graph consists of only one node with val = 1 and it does not have any neighbors.\n```"
},
{
"content": "```\nInput: adjList = []\nOutput: []\nExplanation: This an empty graph, it does not have any nodes.\n```"
}
],
"readme_constraints": "- The number of nodes in the graph is in the range `[0, 100]`.\n- `1 <= Node.val <= 100`\n- `Node.val` is unique for each node.\n- There are no repeated edges and no self-loops in the graph.\n- The Graph is connected and all nodes can be visited starting from the given node.",
"readme_additional": "",
"solution_imports": "from leetcode_py import GraphNode",
"solution_methods": [
{
"name": "clone_graph",
"parameters": "node: GraphNode | None",
"return_type": "GraphNode | None",
"dummy_return": "None"
}
],
"test_imports": "import pytest\n\nfrom leetcode_py import GraphNode\nfrom leetcode_py.test_utils import logged_test\n\nfrom .solution import Solution",
"test_class_name": "CloneGraph",
"test_helper_methods": [
{ "name": "setup_method", "parameters": "", "body": "self.solution = Solution()" }
],
"test_methods": [
{
"name": "test_clone_graph",
"parametrize": "adj_list",
"parametrize_typed": "adj_list: list[list[int]]",
"test_cases": "[[[2, 4], [1, 3], [2, 4], [1, 3]], [[]], []]",
"body": "node = GraphNode.from_adjacency_list(adj_list)\nresult = self.solution.clone_graph(node)\nassert result.is_clone(node) if result else node is None"
}
],
"playground_imports": "from solution import Solution\n\nfrom leetcode_py import GraphNode",
"playground_test_case": "# Example test case\nadj_list = [[2,4],[1,3],[2,4],[1,3]]\nnode = GraphNode.from_adjacency_list(adj_list)",
"playground_execution": "result = Solution().clone_graph(node)\nresult",
"playground_assertion": "assert result.is_clone(node) if result else node is None"
}
50 changes: 50 additions & 0 deletions .templates/leetcode/json/evaluate_reverse_polish_notation.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"problem_name": "evaluate_reverse_polish_notation",
"solution_class_name": "Solution",
"problem_number": "150",
"problem_title": "Evaluate Reverse Polish Notation",
"difficulty": "Medium",
"topics": "Array, Math, Stack",
"tags": ["grind-75"],
"readme_description": "You are given an array of strings `tokens` that represents an arithmetic expression in a **Reverse Polish Notation**.\n\nEvaluate the expression. Return *an integer that represents the value of the expression*.\n\n**Note that:**\n\n- The valid operators are `'+'`, `'-'`, `'*'`, and `'/'`.\n- Each operand may be an integer or another expression.\n- The division between two integers always **truncates toward zero**.\n- There will not be any division by zero.\n- The input represents a valid arithmetic expression in a reverse polish notation.\n- The answer and all the intermediate calculations can be represented in a **32-bit** integer.",
"readme_examples": [
{
"content": "```\nInput: tokens = [\"2\",\"1\",\"+\",\"3\",\"*\"]\nOutput: 9\n```\n**Explanation:** ((2 + 1) * 3) = 9"
},
{
"content": "```\nInput: tokens = [\"4\",\"13\",\"5\",\"/\",\"+\"]\nOutput: 6\n```\n**Explanation:** (4 + (13 / 5)) = 6"
},
{
"content": "```\nInput: tokens = [\"10\",\"6\",\"9\",\"3\",\"+\",\"-11\",\"*\",\"/\",\"*\",\"17\",\"+\",\"5\",\"+\"]\nOutput: 22\n```\n**Explanation:** ((10 * (6 / ((9 + 3) * -11))) + 17) + 5 = 22"
}
],
"readme_constraints": "- `1 <= tokens.length <= 10^4`\n- `tokens[i]` is either an operator: `\"+\"`, `\"-\"`, `\"*\"`, or `\"/\"`, or an integer in the range `[-200, 200]`.",
"readme_additional": "",
"solution_imports": "",
"solution_methods": [
{
"name": "eval_rpn",
"parameters": "tokens: list[str]",
"return_type": "int",
"dummy_return": "0"
}
],
"test_imports": "import pytest\nfrom leetcode_py.test_utils import logged_test\nfrom .solution import Solution",
"test_class_name": "EvaluateReversePolishNotation",
"test_helper_methods": [
{ "name": "setup_method", "parameters": "", "body": "self.solution = Solution()" }
],
"test_methods": [
{
"name": "test_eval_rpn",
"parametrize": "tokens, expected",
"parametrize_typed": "tokens: list[str], expected: int",
"test_cases": "[([\"2\", \"1\", \"+\", \"3\", \"*\"], 9), ([\"4\", \"13\", \"5\", \"/\", \"+\"], 6), ([\"10\", \"6\", \"9\", \"3\", \"+\", \"-11\", \"*\", \"/\", \"*\", \"17\", \"+\", \"5\", \"+\"], 22)]",
"body": "result = self.solution.eval_rpn(tokens)\nassert result == expected"
}
],
"playground_imports": "from solution import Solution",
"playground_test_case": "# Example test case\ntokens = [\\\"2\\\", \\\"1\\\", \\\"+\\\", \\\"3\\\", \\\"*\\\"]\nexpected = 9",
"playground_execution": "result = Solution().eval_rpn(tokens)\nresult",
"playground_assertion": "assert result == expected"
}
47 changes: 47 additions & 0 deletions .templates/leetcode/json/minimum_height_trees.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"problem_name": "minimum_height_trees",
"solution_class_name": "Solution",
"problem_number": "310",
"problem_title": "Minimum Height Trees",
"difficulty": "Medium",
"topics": "Depth-First Search, Breadth-First Search, Graph, Topological Sort",
"tags": ["grind-75"],
"readme_description": "A tree is an undirected graph in which any two vertices are connected by *exactly* one path. In other words, any connected graph without simple cycles is a tree.\n\nGiven a tree of `n` nodes labelled from `0` to `n - 1`, and an array of `n - 1` `edges` where `edges[i] = [ai, bi]` indicates that there is an undirected edge between the two nodes `ai` and `bi` in the tree, you can choose any node of the tree as the root. When you select a node `x` as the root, the result tree has height `h`. Among all possible rooted trees, those with minimum height (i.e. `min(h)`) are called **minimum height trees** (MHTs).\n\nReturn *a list of all **MHTs'** root labels*. You can return the answer in **any order**.\n\nThe **height** of a rooted tree is the number of edges on the longest downward path between the root and a leaf.",
"readme_examples": [
{
"content": "<img alt=\"\" src=\"https://assets.leetcode.com/uploads/2020/09/01/e1.jpg\" style=\"width: 800px; height: 213px;\" />\n\n```\nInput: n = 4, edges = [[1,0],[1,2],[1,3]]\nOutput: [1]\nExplanation: As shown, the height of the tree is 1 when the root is the node with label 1 which is the only MHT.\n```"
},
{
"content": "<img alt=\"\" src=\"https://assets.leetcode.com/uploads/2020/09/01/e2.jpg\" style=\"width: 800px; height: 321px;\" />\n\n```\nInput: n = 6, edges = [[3,0],[3,1],[3,2],[3,4],[5,4]]\nOutput: [3,4]\n```"
}
],
"readme_constraints": "- `1 <= n <= 2 * 10^4`\n- `edges.length == n - 1`\n- `0 <= ai, bi < n`\n- `ai != bi`\n- All the pairs `(ai, bi)` are distinct.\n- The given input is **guaranteed** to be a tree and there will be **no repeated** edges.",
"readme_additional": "",
"solution_imports": "",
"solution_methods": [
{
"name": "find_min_height_trees",
"parameters": "n: int, edges: list[list[int]]",
"return_type": "list[int]",
"dummy_return": "[]"
}
],
"test_imports": "import pytest\nfrom leetcode_py.test_utils import logged_test\nfrom .solution import Solution",
"test_class_name": "MinimumHeightTrees",
"test_helper_methods": [
{ "name": "setup_method", "parameters": "", "body": "self.solution = Solution()" }
],
"test_methods": [
{
"name": "test_find_min_height_trees",
"parametrize": "n, edges, expected",
"parametrize_typed": "n: int, edges: list[list[int]], expected: list[int]",
"test_cases": "[(4, [[1,0],[1,2],[1,3]], [1]), (6, [[3,0],[3,1],[3,2],[3,4],[5,4]], [3,4]), (1, [], [0])]",
"body": "result = self.solution.find_min_height_trees(n, edges)\nassert sorted(result) == sorted(expected)"
}
],
"playground_imports": "from solution import Solution",
"playground_test_case": "# Example test case\nn = 4\nedges = [[1,0],[1,2],[1,3]]\nexpected = [1]",
"playground_execution": "result = Solution().find_min_height_trees(n, edges)\nresult",
"playground_assertion": "assert sorted(result) == sorted(expected)"
}
50 changes: 50 additions & 0 deletions .templates/leetcode/json/task_scheduler.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"problem_name": "task_scheduler",
"solution_class_name": "Solution",
"problem_number": "621",
"problem_title": "Task Scheduler",
"difficulty": "Medium",
"topics": "Array, Hash Table, Greedy, Sorting, Heap (Priority Queue), Counting",
"tags": ["grind-75"],
"readme_description": "You are given an array of CPU `tasks`, each labeled with a letter from A to Z, and a number `n`. Each CPU interval can be idle or allow the completion of one task. Tasks can be completed in any order, but there's a constraint: there has to be a gap of **at least** `n` intervals between two tasks with the same label.\n\nReturn the **minimum** number of CPU intervals required to complete all tasks.",
"readme_examples": [
{
"content": "```\nInput: tasks = [\"A\",\"A\",\"A\",\"B\",\"B\",\"B\"], n = 2\nOutput: 8\n```\n**Explanation:** A possible sequence is: A -> B -> idle -> A -> B -> idle -> A -> B.\n\nAfter completing task A, you must wait two intervals before doing A again. The same applies to task B. In the 3rd interval, neither A nor B can be done, so you idle. By the 4th interval, you can do A again as 2 intervals have passed."
},
{
"content": "```\nInput: tasks = [\"A\",\"C\",\"A\",\"B\",\"D\",\"B\"], n = 1\nOutput: 6\n```\n**Explanation:** A possible sequence is: A -> B -> C -> D -> A -> B.\n\nWith a cooling interval of 1, you can repeat a task after just one other task."
},
{
"content": "```\nInput: tasks = [\"A\",\"A\",\"A\", \"B\",\"B\",\"B\"], n = 3\nOutput: 10\n```\n**Explanation:** A possible sequence is: A -> B -> idle -> idle -> A -> B -> idle -> idle -> A -> B.\n\nThere are only two types of tasks, A and B, which need to be separated by 3 intervals. This leads to idling twice between repetitions of these tasks."
}
],
"readme_constraints": "- `1 <= tasks.length <= 10^4`\n- `tasks[i]` is an uppercase English letter.\n- `0 <= n <= 100`",
"readme_additional": "",
"solution_imports": "",
"solution_methods": [
{
"name": "least_interval",
"parameters": "tasks: list[str], n: int",
"return_type": "int",
"dummy_return": "0"
}
],
"test_imports": "import pytest\nfrom leetcode_py.test_utils import logged_test\nfrom .solution import Solution",
"test_class_name": "TaskScheduler",
"test_helper_methods": [
{ "name": "setup_method", "parameters": "", "body": "self.solution = Solution()" }
],
"test_methods": [
{
"name": "test_least_interval",
"parametrize": "tasks, n, expected",
"parametrize_typed": "tasks: list[str], n: int, expected: int",
"test_cases": "[([\"A\", \"A\", \"A\", \"B\", \"B\", \"B\"], 2, 8), ([\"A\", \"C\", \"A\", \"B\", \"D\", \"B\"], 1, 6), ([\"A\", \"A\", \"A\", \"B\", \"B\", \"B\"], 3, 10)]",
"body": "result = self.solution.least_interval(tasks, n)\nassert result == expected"
}
],
"playground_imports": "from solution import Solution",
"playground_test_case": "# Example test case\ntasks = [\\\"A\\\", \\\"A\\\", \\\"A\\\", \\\"B\\\", \\\"B\\\", \\\"B\\\"]\nn = 2\nexpected = 8",
"playground_execution": "result = Solution().least_interval(tasks, n)\nresult",
"playground_assertion": "assert result == expected"
}
47 changes: 47 additions & 0 deletions .templates/leetcode/json/validate_binary_search_tree.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"problem_name": "validate_binary_search_tree",
"solution_class_name": "Solution",
"problem_number": "98",
"problem_title": "Validate Binary Search Tree",
"difficulty": "Medium",
"topics": "Tree, Depth-First Search, Binary Search Tree, Binary Tree",
"tags": ["grind-75"],
"readme_description": "Given the `root` of a binary tree, determine if it is a valid binary search tree (BST).\n\nA **valid BST** is defined as follows:\n\n- The left subtree of a node contains only nodes with keys **strictly less than** the node's key.\n- The right subtree of a node contains only nodes with keys **strictly greater than** the node's key.\n- Both the left and right subtrees must also be binary search trees.",
"readme_examples": [
{
"content": "![Example 1](https://assets.leetcode.com/uploads/2020/12/01/tree1.jpg)\n\n```\nInput: root = [2,1,3]\nOutput: true\n```"
},
{
"content": "![Example 2](https://assets.leetcode.com/uploads/2020/12/01/tree2.jpg)\n\n```\nInput: root = [5,1,4,null,null,3,6]\nOutput: false\n```\n**Explanation:** The root node's value is 5 but its right child's value is 4."
}
],
"readme_constraints": "- The number of nodes in the tree is in the range `[1, 10^4]`.\n- `-2^31 <= Node.val <= 2^31 - 1`",
"readme_additional": "",
"solution_imports": "from leetcode_py import TreeNode",
"solution_methods": [
{
"name": "is_valid_bst",
"parameters": "root: TreeNode[int] | None",
"return_type": "bool",
"dummy_return": "False"
}
],
"test_imports": "import pytest\nfrom leetcode_py.test_utils import logged_test\nfrom leetcode_py import TreeNode\nfrom .solution import Solution",
"test_class_name": "ValidateBinarySearchTree",
"test_helper_methods": [
{ "name": "setup_method", "parameters": "", "body": "self.solution = Solution()" }
],
"test_methods": [
{
"name": "test_is_valid_bst",
"parametrize": "root_list, expected",
"parametrize_typed": "root_list: list[int | None], expected: bool",
"test_cases": "[([2, 1, 3], True), ([5, 1, 4, None, None, 3, 6], False), ([2, 1, 3], True), ([1], True), ([1, 1], False)]",
"body": "root = TreeNode.from_list(root_list)\nresult = self.solution.is_valid_bst(root)\nassert result == expected"
}
],
"playground_imports": "from solution import Solution\nfrom leetcode_py import TreeNode",
"playground_test_case": "# Example test case\nroot_list: list[int | None] = [2, 1, 3]\nexpected = True",
"playground_execution": "root = TreeNode.from_list(root_list)\nresult = Solution().is_valid_bst(root)\nresult",
"playground_assertion": "assert result == expected"
}
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
PYTHON_VERSION = 3.13
PROBLEM ?= invert_binary_tree
PROBLEM ?= task_scheduler
FORCE ?= 0

sync_submodules:
Expand Down
Loading
Loading