Skip to content

Commit 9d24cd3

Browse files
committed
Move all problems in notebooks to Leetcode dir, and rename notebooks
1 parent 87c8641 commit 9d24cd3

File tree

52 files changed

+1953
-1843
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+1953
-1843
lines changed

leetcode/1-two-sum/solution_v2.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""
22
See prefix sums notebook for explanation.
33
"""
4+
from typing import List
45

56

67
class Solution:
@@ -10,3 +11,13 @@ def twoSum(self, nums: List[int], target: int) -> List[int]:
1011
if val in comps and i != comps[val]:
1112
return [i, comps[val]]
1213
comps[target - val] = i
14+
15+
16+
s = Solution()
17+
cases = [
18+
([2, 7, 11, 15], 9, [0, 1]),
19+
([-1, -2, -3, -4, -5], -8, [2, 4])
20+
]
21+
for arr, target, expected in cases:
22+
actual = s.twoSum(arr, target)
23+
assert sorted(expected) == sorted(actual), f"arr,target: {expected} != {actual}"
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
from collections import Counter
2+
from typing import List
3+
4+
5+
class Solution:
6+
def carPooling(self, trips: List[List[int]], capacity: int) -> bool:
7+
first, last = float('inf'), -float('inf')
8+
stops = Counter()
9+
for passengers, start, end in trips:
10+
stops[start] += passengers
11+
stops[end] -= passengers
12+
first = min(first, start)
13+
last = max(last, end)
14+
15+
seats = 0
16+
for i in range(first, last+1):
17+
seats += stops[i]
18+
if seats > capacity:
19+
return False
20+
return True
21+
22+
23+
s = Solution()
24+
cases = [
25+
([[2, 1, 5], [3, 3, 7]], 4, False),
26+
([[2, 1, 5], [3, 3, 7]], 5, True),
27+
([[2, 1, 5], [3, 5, 7]], 3, True),
28+
([[3, 2, 7], [3, 7, 9], [8, 3, 9]], 11, True),
29+
]
30+
31+
for trips, capacity, expected in cases:
32+
actual = s.carPooling(trips, capacity)
33+
assert actual == expected, f"{trips, capacity}: {expected} != {actual}"
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+
4+
class Solution:
5+
def corpFlightBookings(self, bookings: List[List[int]], n: int) -> List[int]:
6+
flights = [0] * (n+1)
7+
for first, last, count in bookings:
8+
flights[first-1] += count
9+
flights[last] -= count
10+
for i in range(1, n):
11+
flights[i] += flights[i-1]
12+
return flights[:-1]
13+
14+
15+
s = Solution()
16+
cases = [
17+
([[1, 2, 10], [2, 3, 20], [2, 5, 25]], 5, [10, 55, 45, 25, 25])
18+
]
19+
for bookings, n, expected in cases:
20+
actual = s.corpFlightBookings(bookings, n)
21+
assert actual == expected, f"{bookings, n}: {expected} != {actual}"
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
from collections import Counter
2+
from typing import List
3+
4+
5+
def interval_sweep_shitty(requests):
6+
"""
7+
Given a list of ranges, return an array
8+
where arr[i] equals the number of ranges
9+
including i.
10+
"""
11+
bounds_counts = Counter()
12+
first, last = float('inf'), -float('inf')
13+
for start, end in requests:
14+
bounds_counts[start] += 1
15+
bounds_counts[end+1] -= 1
16+
first = min(start, end, first)
17+
last = max(start, end, last)
18+
19+
frequency = 0
20+
overlap_count = []
21+
for val in range(first, last+1):
22+
frequency += bounds_counts[val]
23+
overlap_count.append(frequency)
24+
return overlap_count
25+
26+
27+
def interval_sweep(nums_len, requests):
28+
"""
29+
Same as above, but borrowing from @lee215's
30+
technique which is faster.
31+
"""
32+
counts = [0] * (nums_len+1)
33+
for start, end in requests:
34+
counts[start] += 1
35+
counts[end+1] -= 1
36+
37+
for i in range(1, nums_len+1):
38+
counts[i] += counts[i-1]
39+
return counts
40+
41+
42+
class Solution:
43+
def maxSumRangeQuery(self, nums: List[int], requests: List[List[int]]) -> int:
44+
nums.sort(reverse=True)
45+
overlap_count = interval_sweep(len(nums), requests)
46+
max_sum = 0
47+
for i, frequency in enumerate(sorted(overlap_count[:-1], reverse=True)):
48+
max_sum += frequency*nums[i]
49+
return max_sum % (10**9 + 7)
50+
51+
52+
s = Solution()
53+
cases = [
54+
([1, 2, 3, 4, 5], [[1, 3], [0, 1]], 19),
55+
([1, 2, 3, 4, 5, 6], [[0, 1]], 11),
56+
([1, 2, 3, 4, 5, 10], [[0, 2], [1, 3], [1, 1]], 47)
57+
]
58+
for nums, requests, expected in cases:
59+
actual = s.maxSumRangeQuery(nums, requests)
60+
assert actual == expected, f"{nums, requests}: {expected} != {actual}"
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from collections import Counter
2+
3+
4+
def majority(arr, lo, hi):
5+
if lo == hi:
6+
return arr[lo]
7+
mid = (hi+lo)//2
8+
lo_majority = majority(arr, lo, mid)
9+
hi_majority = majority(arr, mid+1, hi)
10+
11+
# if both have same majority, then return it
12+
if lo_majority == hi_majority:
13+
return lo_majority
14+
# Otherwise, count the occurrences and return the best
15+
return Counter(arr[lo:hi+1]).most_common(1)[0][0]
16+
17+
18+
cases = [
19+
([3, 3, 4], 3),
20+
([2, 2, 1, 1, 1], 1),
21+
([1, 2, 1, 2, 1], 1),
22+
([1, 1, 1, 2], 1),
23+
]
24+
25+
for arr, expected in cases:
26+
actual = majority(arr, 0, len(arr)-1)
27+
assert actual == expected, f"{arr}: {expected} != {actual}"
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
from typing import List
2+
3+
PHONE_PAD = {
4+
'2': ["a", "b", "c"],
5+
'3': ["d", "e", "f"],
6+
'4': ["g", "h", "i"],
7+
'5': ["j", "k", "l"],
8+
'6': ["m", "n", "o"],
9+
'7': ["p", "q", "r", "s"],
10+
'8': ["t", "u", "v"],
11+
'9': ["w", "x", "y", "z"],
12+
}
13+
14+
15+
def combine(c, strs):
16+
return [c+string for string in strs] if strs else [c]
17+
18+
19+
class Solution:
20+
def letterCombinations(self, nums: str, i=0) -> List[str]:
21+
if i >= len(nums):
22+
return []
23+
solution = []
24+
for c in PHONE_PAD[nums[i]]:
25+
solution += combine(c, self.letterCombinations(nums, i+1))
26+
return solution
27+
28+
29+
s = Solution()
30+
cases = [
31+
("23", ['ad', 'ae', 'af', 'bd', 'be', 'bf', 'cd', 'ce', 'cf']),
32+
("2", ['a', 'b', 'c']),
33+
("", [])
34+
]
35+
for number, letters in cases:
36+
actual = s.letterCombinations(number)
37+
assert sorted(actual) == sorted(letters)
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
from collections import defaultdict
2+
from typing import List
3+
4+
5+
def visit(node, child_nodes, ancestors):
6+
if node not in child_nodes:
7+
return True
8+
if node in ancestors:
9+
return False
10+
ancestors.add(node)
11+
valid = True
12+
for child in child_nodes[node]:
13+
valid &= visit(child, child_nodes, ancestors)
14+
ancestors.remove(node)
15+
del child_nodes[node]
16+
return valid
17+
18+
19+
class Solution:
20+
def canFinish(self, num_courses: int, prerequisites: List[List[int]]) -> bool:
21+
starting_nodes = set([i for i in range(num_courses)])
22+
child_nodes = defaultdict(set)
23+
for course, prereq in prerequisites:
24+
child_nodes[prereq].add(course)
25+
starting_nodes.remove(course) if course in starting_nodes else None
26+
27+
while starting_nodes:
28+
ancestors = set()
29+
current = starting_nodes.pop()
30+
if not visit(current, child_nodes, ancestors):
31+
return False
32+
return not (starting_nodes or child_nodes)
33+
34+
35+
s = Solution()
36+
s.canFinish(8, [[1, 0], [2, 6], [1, 7], [5, 1], [6, 4], [7, 0], [0, 5]])
37+
s.canFinish(3, [[1, 0], [1, 2], [0, 1]])
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from typing import List
2+
3+
4+
class Solution:
5+
def minSubArrayLen(self, s: int, nums: List[int]) -> int:
6+
csum = l = 0
7+
best = float('inf')
8+
for r, val in enumerate(nums):
9+
csum += val
10+
while csum - nums[l] >= s and l < len(nums):
11+
csum -= nums[l]
12+
l += 1
13+
best = min(r-l+1, best) if csum >= s else best
14+
return best if best != float('inf') else 0
15+
16+
17+
cases = [
18+
(7, [2, 3, 1, 2, 4, 3], 2),
19+
(7, [0, 0, 0], 0),
20+
(7, [10, 10, 10], 1),
21+
(7, [], 0)
22+
]
23+
24+
sol = Solution()
25+
for s, nums, expected in cases:
26+
actual = sol.minSubArrayLen(s, nums)
27+
assert actual == expected, f"{nums, s}: {expected} != {actual}"
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
class ListNode:
2+
def __init__(self, val=0, next=None):
3+
self.val = val
4+
self.next = next
5+
6+
7+
class Solution:
8+
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
9+
if not (l1 and l2):
10+
return l1 if not l2 else l2
11+
if l1.val <= l2.val:
12+
next_node = l1
13+
l1 = l1.next
14+
else:
15+
next_node = l2
16+
l2 = l2.next
17+
next_node.next = self.mergeTwoLists(l1, l2)
18+
return next_node
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
from collections import defaultdict
2+
from typing import List
3+
4+
5+
class CycleExistsError(Exception):
6+
pass
7+
8+
9+
def visit(course, next_courses, visited, ancestors, top_order):
10+
if course in visited:
11+
return
12+
if course in ancestors:
13+
raise CycleExistsError
14+
15+
ancestors.add(course)
16+
for child in next_courses[course]:
17+
visit(child, next_courses, visited, ancestors, top_order)
18+
ancestors.remove(course)
19+
visited.add(course)
20+
top_order.append(course)
21+
22+
23+
class Solution:
24+
def findOrder(self, num_courses: int, prerequisites: List[List[int]]) -> List[int]:
25+
starting_courses = set([i for i in range(num_courses)])
26+
next_courses = defaultdict(set)
27+
for course, prereq in prerequisites:
28+
next_courses[prereq].add(course)
29+
starting_courses.remove(course) if course in starting_courses else None
30+
if not starting_courses:
31+
return []
32+
33+
top_order = []
34+
visited = set()
35+
while starting_courses:
36+
ancestors = set()
37+
curr_course = starting_courses.pop()
38+
try:
39+
visit(curr_course, next_courses, visited, ancestors, top_order)
40+
except CycleExistsError:
41+
return []
42+
return top_order[::-1] if len(visited) == num_courses else []
43+
44+
45+
s = Solution()
46+
cases = [
47+
(2, [[1, 0]]),
48+
(2, [[1, 0], [0, 1]]),
49+
(3, [[1, 0], [0, 1]]),
50+
(4, [[1, 0], [2, 1]])
51+
52+
]
53+
for n_courses, prereqs in cases:
54+
print(s.findOrder(n_courses, prereqs))

0 commit comments

Comments
 (0)