-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f15fe47
commit 07f6110
Showing
5 changed files
with
267 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
# Your car starts at position 0 and speed +1 on an infinite number line. Your car can go into negative positions. Your car drives automatically according to a sequence of instructions 'A' (accelerate) and 'R' (reverse): | ||
# | ||
# - When you get an instruction 'A', your car does the following: | ||
# - position += speed | ||
# - speed *= 2 | ||
# - When you get an instruction 'R', your car does the following: | ||
# - If your speed is positive then speed = -1 | ||
# - otherwise speed = 1 | ||
# Your position stays the same. | ||
# | ||
# For example, after commands "AAR", your car goes to positions 0 --> 1 --> 3 --> 3, and your speed goes to 1 --> 2 --> 4 --> -1. | ||
# Given a target position target, return the length of the shortest sequence of instructions to get there. | ||
# | ||
# Example 1: | ||
# | ||
# Input: target = 3 | ||
# Output: 2 | ||
# Explanation: | ||
# The shortest instruction sequence is "AA". | ||
# Your position goes from 0 --> 1 --> 3. | ||
# | ||
# Example 2: | ||
# | ||
# Input: target = 6 | ||
# Output: 5 | ||
# Explanation: | ||
# The shortest instruction sequence is "AAARA". | ||
# Your position goes from 0 --> 1 --> 3 --> 7 --> 7 --> 6. | ||
# | ||
# Constraints: | ||
# | ||
# 1 <= target <= 10^4 | ||
|
||
|
||
# https://leetcode.com/problems/race-car/discuss/1512080/Greedy-Approach-oror-Normal-conditions-oror-94-faster-oror-Well-Coded | ||
# Idea: | ||
# The key point is move close to that point and then start reversing the gear based on conditions. | ||
# If you are still before to the target and speed is reverse(i.e. deaccelerating) or if you are ahead of target and speed is positive (i.e. accelerating) then reverse the speed. | ||
# | ||
# There are two strategies to get to the target distance: | ||
# 1. We go pass it, then come back. | ||
# For example, the target is 2, we accelerate twice to 3, then reverse and come back (the new target is then 3 - 2 = 1. | ||
# 2. We get super close to it, then reverse accelerate a few times, then reverse back to the target | ||
# For example, the target is 2, we accelerate once to 1, then reverse to accelerate 0 times, and reverse again. The new target will be 1 | ||
class Solution: | ||
def racecar(self, target: int) -> int: | ||
q = [] | ||
q.append((0, 0, 1)) # (step, pos, speed) | ||
while q: | ||
step, pos, speed = q.pop(0) | ||
if pos == target: | ||
return step | ||
|
||
q.append((step + 1, pos + speed, speed * 2)) | ||
|
||
# If you are back to the target and speed is reverse | ||
# or if you are ahead of target and speed is positive then reverse the speed | ||
if (pos + speed < target and speed < 0) or ( | ||
pos + speed > target and speed > 0 | ||
): | ||
reversed_speed = -1 if speed > 0 else 1 | ||
q.append((step + 1, pos, reversed_speed)) | ||
return -1 |
75 changes: 75 additions & 0 deletions
75
Python/2096. Step-By-Step Directions From a Binary Tree Node to Another.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
# You are given the root of a binary tree with n nodes. Each node is uniquely assigned a value from 1 to n. You are also given an integer startValue representing the value of the start node s, and a different integer destValue representing the value of the destination node t. | ||
# Find the shortest path starting from node s and ending at node t. Generate step-by-step directions of such path as a string consisting of only the uppercase letters 'L', 'R', and 'U'. Each letter indicates a specific direction: | ||
# | ||
# 'L' means to go from a node to its left child node. | ||
# 'R' means to go from a node to its right child node. | ||
# 'U' means to go from a node to its parent node. | ||
# | ||
# Return the step-by-step directions of the shortest path from node s to node t. | ||
# | ||
# Example 1: | ||
# | ||
# Input: root = [5,1,2,3,null,6,4], startValue = 3, destValue = 6 | ||
# Output: "UURL" | ||
# Explanation: The shortest path is: 3 → 1 → 5 → 2 → 6. | ||
# | ||
# Example 2: | ||
# | ||
# Input: root = [2,1], startValue = 2, destValue = 1 | ||
# Output: "L" | ||
# Explanation: The shortest path is: 2 → 1. | ||
# | ||
# Constraints: | ||
# | ||
# The number of nodes in the tree is n. | ||
# 2 <= n <= 10^5 | ||
# 1 <= Node.val <= n | ||
# All the values in the tree are unique. | ||
# 1 <= startValue, destValue <= n | ||
# startValue != destValue | ||
|
||
|
||
# Definition for a binary tree node. | ||
# class TreeNode: | ||
# def __init__(self, val=0, left=None, right=None): | ||
# self.val = val | ||
# self.left = left | ||
# self.right = right | ||
|
||
|
||
class Solution: | ||
def getDirections( | ||
self, root: Optional[TreeNode], startValue: int, destValue: int | ||
) -> str: | ||
# Return lowest common ancestor of start and dest nodes. | ||
def lca(root): | ||
if not root: | ||
return None | ||
if root.val == startValue or root.val == destValue: | ||
return root | ||
|
||
l = lca(root.left) | ||
r = lca(root.right) | ||
|
||
if l and r: # p and q are on different sides | ||
return root | ||
if l: # p and q are both on the left side | ||
return l | ||
if r: # p and q are both on the right side | ||
return r | ||
|
||
root = lca(root) # only this sub-tree matters | ||
|
||
ps = pd = "" | ||
st = [(root, "")] | ||
while st: | ||
node, path = st.pop() | ||
if node.val == startValue: | ||
ps = path | ||
if node.val == destValue: | ||
pd = path | ||
if node.left: | ||
st.append((node.left, path + "L")) | ||
if node.right: | ||
st.append((node.right, path + "R")) | ||
return "U" * len(ps) + pd |
81 changes: 81 additions & 0 deletions
81
Python/2115. Find All Possible Recipes from Given Supplies.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
# You have information about n different recipes. You are given a string array recipes and a 2D string array ingredients. The ith recipe has the name recipes[i], and you can create it if you have all the needed ingredients from ingredients[i]. Ingredients to a recipe may need to be created from other recipes, i.e., ingredients[i] may contain a string that is in recipes. | ||
# You are also given a string array supplies containing all the ingredients that you initially have, and you have an infinite supply of all of them. | ||
# Return a list of all the recipes that you can create. You may return the answer in any order. | ||
# Note that two recipes may contain each other in their ingredients. | ||
# | ||
# Example 1: | ||
# | ||
# Input: recipes = ["bread"], ingredients = [["yeast","flour"]], supplies = ["yeast","flour","corn"] | ||
# Output: ["bread"] | ||
# Explanation: | ||
# We can create "bread" since we have the ingredients "yeast" and "flour". | ||
# | ||
# Example 2: | ||
# | ||
# Input: recipes = ["bread","sandwich"], ingredients = [["yeast","flour"],["bread","meat"]], supplies = ["yeast","flour","meat"] | ||
# Output: ["bread","sandwich"] | ||
# Explanation: | ||
# We can create "bread" since we have the ingredients "yeast" and "flour". | ||
# We can create "sandwich" since we have the ingredient "meat" and can create the ingredient "bread". | ||
# | ||
# Example 3: | ||
# | ||
# Input: recipes = ["bread","sandwich","burger"], ingredients = [["yeast","flour"],["bread","meat"],["sandwich","meat","bread"]], supplies = ["yeast","flour","meat"] | ||
# Output: ["bread","sandwich","burger"] | ||
# Explanation: | ||
# We can create "bread" since we have the ingredients "yeast" and "flour". | ||
# We can create "sandwich" since we have the ingredient "meat" and can create the ingredient "bread". | ||
# We can create "burger" since we have the ingredient "meat" and can create the ingredients "bread" and "sandwich". | ||
# | ||
# Constraints: | ||
# | ||
# n == recipes.length == ingredients.length | ||
# 1 <= n <= 100 | ||
# 1 <= ingredients[i].length, supplies.length <= 100 | ||
# 1 <= recipes[i].length, ingredients[i][j].length, supplies[k].length <= 10 | ||
# recipes[i], ingredients[i][j], and supplies[k] consist only of lowercase English letters. | ||
# All the values of recipes and supplies combined are unique. | ||
# Each ingredients[i] does not contain any duplicate values. | ||
|
||
|
||
# Topological sort | ||
# | ||
# supplies -> recipes | ||
# ingredients: the relationship of supplies -> recipes | ||
# | ||
# e.g. | ||
# Input | ||
# supplies = ["yeast","flour","meat"] | ||
# ingredients = [["yeast","flour"],["bread","meat"]] | ||
# recipes = ["bread","sandwich"] | ||
# | ||
# Output | ||
# ["bread","sandwich"] | ||
from collections import defaultdict, deque, Counter | ||
|
||
|
||
class Solution: | ||
def findAllRecipes( | ||
self, recipes: List[str], ingredients: List[List[str]], supplies: List[str] | ||
) -> List[str]: | ||
in_degrees = Counter() | ||
graph = defaultdict(list) | ||
for recipe, ingredient in zip(recipes, ingredients): | ||
in_degrees[recipe] = len(ingredient) | ||
for supply in ingredient: | ||
graph[supply].append(recipe) | ||
|
||
recipes = set(recipes) | ||
res = [] | ||
q = deque(supplies) | ||
while q: | ||
u = q.popleft() | ||
|
||
if u in recipes: | ||
res.append(u) | ||
|
||
for v in graph[u]: | ||
in_degrees[v] -= 1 | ||
if in_degrees[v] == 0: | ||
q.append(v) | ||
return res |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
# You are given an m x n binary matrix grid. | ||
# In one operation, you can choose any row or column and flip each value in that row or column (i.e., changing all 0's to 1's, and all 1's to 0's). | ||
# Return true if it is possible to remove all 1's from grid using any number of operations or false otherwise. | ||
# | ||
# Example 1: | ||
# | ||
# Input: grid = [[0,1,0],[1,0,1],[0,1,0]] | ||
# Output: true | ||
# Explanation: One possible way to remove all 1's from grid is to: | ||
# - Flip the middle row | ||
# - Flip the middle column | ||
# | ||
# Example 2: | ||
# | ||
# Input: grid = [[1,1,0],[0,0,0],[0,0,0]] | ||
# Output: false | ||
# Explanation: It is impossible to remove all 1's from grid. | ||
# | ||
# Example 3: | ||
# | ||
# Input: grid = [[0]] | ||
# Output: true | ||
# Explanation: There are no 1's in grid. | ||
# | ||
# Constraints: | ||
# | ||
# m == grid.length | ||
# n == grid[i].length | ||
# 1 <= m, n <= 300 | ||
# grid[i][j] is either 0 or 1. | ||
|
||
|
||
# https://leetcode.com/problems/remove-all-ones-with-row-and-column-flips/discuss/1695472/Python-3-or-Simple-Explanation | ||
# 1. For each row or col, we only need to flip it once or do not flip. | ||
# (Flip 2, 4, 6,.. times is same as not flip; flip 1, 3, 5, .. times is same as flip once); | ||
# 2. The order of flipping does not matter. | ||
# 3. If after some flips, we can get the all-zero matrix. | ||
# Then for each pair of rows (or cols), they must be exactly same (every element is the same) or completely different (every element is different). | ||
class Solution: | ||
def removeOnes(self, grid: List[List[int]]) -> bool: | ||
m, n = len(grid), len(grid[0]) | ||
row0 = grid[0] | ||
row0_flip = [1 - x for x in grid[0]] | ||
for row in range(1, m): | ||
if grid[row] != row0 and grid[row] != row0_flip: | ||
return False | ||
return True |