Compare commits

...

57 Commits

Author SHA1 Message Date
Deven 88b99caf11 Time: 38 ms (85.56%), Space: 18.1 MB (81.8%) - LeetHub 2025-12-10 16:30:29 -05:00
Deven 2c96c57870 Create README - LeetHub 2025-12-10 16:30:28 -05:00
Deven 6bc1bcb772 Time: 4 ms (13.43%), Space: 18.5 MB (85.36%) - LeetHub 2025-12-08 18:17:52 -05:00
Deven f174c1edea Create README - LeetHub 2025-12-08 18:17:51 -05:00
Deven 3c88ab7152 Time: 67 ms (60.36%), Space: 23.4 MB (9.25%) - LeetHub 2025-12-04 17:28:52 -05:00
Deven cbef5fb714 Create README - LeetHub 2025-12-04 17:28:52 -05:00
Deven c45b01a838 Time: 814 ms (5.02%), Space: 57 MB (17.32%) - LeetHub 2025-12-01 11:54:18 -05:00
Deven cc492aa3b2 Create README - LeetHub 2025-12-01 11:54:17 -05:00
Deven cf8b99d511 Time: 43 ms (93.63%), Space: 18.2 MB (59.46%) - LeetHub 2025-11-30 22:34:41 -05:00
Deven c90ee7f934 Time: 43 ms (93.63%), Space: 18.2 MB (59.46%) - LeetHub 2025-11-30 22:34:13 -05:00
Deven 10ff3a0da5 Create README - LeetHub 2025-11-30 22:34:12 -05:00
Deven 29c783e08b Time: 810 ms (40.98%), Space: 18.7 MB (34.3%) - LeetHub 2025-11-30 20:48:35 -05:00
Deven 79b324dd16 Create README - LeetHub 2025-11-30 20:48:34 -05:00
Deven 6e90bcdc1f Time: 3 ms (93.68%), Space: 18.9 MB (34.98%) - LeetHub 2025-11-29 21:03:42 -05:00
Deven ae4b1056dd Create README - LeetHub 2025-11-29 21:03:42 -05:00
Deven d5e6259f5b Time: 0 ms (100%), Space: 17.6 MB (82.62%) - LeetHub 2025-11-29 20:33:08 -05:00
Deven c6bc37a26c Create README - LeetHub 2025-11-29 20:33:08 -05:00
Deven a7dc8f50f0 Time: 3 ms (99.62%), Space: 20.1 MB (57.74%) - LeetHub 2025-11-29 16:54:38 -05:00
Deven fadfb3c332 Create README - LeetHub 2025-11-29 16:54:38 -05:00
Deven 45404409de Time: 0 ms (100%), Space: 17.9 MB (50.81%) - LeetHub 2025-11-29 15:55:24 -05:00
Deven 71d9f17be7 Create README - LeetHub 2025-11-29 15:55:24 -05:00
Deven d998bb39f3 Time: 0 ms (100%), Space: 18.2 MB (28.84%) - LeetHub 2025-11-26 20:57:36 -05:00
Deven a00735fbac Create README - LeetHub 2025-11-26 20:57:36 -05:00
Deven cfa865059f Time: 0 ms (100%), Space: 18 MB (11.85%) - LeetHub 2025-11-26 20:40:36 -05:00
Deven fe1c7f9bab Create README - LeetHub 2025-11-26 20:40:35 -05:00
Deven 102f60b356 Time: 3 ms (44.97%), Space: 17.5 MB (99.61%) - LeetHub 2025-11-26 20:24:25 -05:00
Deven ae638d92a1 Time: 3 ms (44.97%), Space: 17.9 MB (30.12%) - LeetHub 2025-11-26 20:24:19 -05:00
Deven 80347ff593 Time: 3 ms (44.97%), Space: 17.9 MB (30.12%) - LeetHub 2025-11-26 20:16:52 -05:00
Deven 7d5c422e07 Create README - LeetHub 2025-11-26 20:16:52 -05:00
Deven 1b166a19b6 Time: 35 ms (96.78%), Space: 28.7 MB (69.5%) - LeetHub 2025-11-26 20:03:16 -05:00
Deven 5f2c51e273 Time: N/A (0%), Space: N/A (0%) - LeetHub 2025-11-26 20:01:46 -05:00
Deven 16adc41a13 Create README - LeetHub 2025-11-26 20:01:45 -05:00
Deven f6481508e2 Time: 0 ms (100%), Space: 19 MB (94.49%) - LeetHub 2025-11-26 17:18:01 -05:00
Deven 49c8ea6771 Create README - LeetHub 2025-11-26 17:18:01 -05:00
Deven 8208854e3d Time: 3 ms (73%), Space: 17.8 MB (84.61%) - LeetHub 2025-11-26 17:04:38 -05:00
Deven c191441bc1 Create README - LeetHub 2025-11-26 17:04:38 -05:00
Deven 152c8893bd Time: 3 ms (98.34%), Space: 17.9 MB (61.48%) - LeetHub 2025-11-26 16:51:49 -05:00
Deven fa5b9fed70 Time: 3 ms (98.34%), Space: 17.9 MB (61.48%) - LeetHub 2025-11-26 16:48:12 -05:00
Deven 2da1f08a05 Create README - LeetHub 2025-11-26 16:48:12 -05:00
Deven 1f1aa6556e Time: 40 ms (22.41%), Space: 40.9 MB (23.28%) - LeetHub 2025-11-26 15:57:26 -05:00
Deven be925e9060 Time: 40 ms (22.41%), Space: 40.9 MB (23.28%) - LeetHub 2025-11-26 15:49:58 -05:00
Deven 1aef61ac76 Create README - LeetHub 2025-11-26 15:49:58 -05:00
Deven 0d4a52234a Time: 363 ms (42.41%), Space: 17.8 MB (83.35%) - LeetHub 2025-11-26 15:33:48 -05:00
Deven 05038ff089 Time: 5673 ms (9.42%), Space: 17.8 MB (59.54%) - LeetHub 2025-11-26 15:32:56 -05:00
Deven 867399287f Time: 5673 ms (9.42%), Space: 17.8 MB (59.54%) - LeetHub 2025-11-26 15:19:27 -05:00
Deven 72ef28dd40 Create README - LeetHub 2025-11-26 15:19:26 -05:00
Deven b7ad28921e Time: 15 ms (80.93%), Space: 18.1 MB (11.97%) - LeetHub 2025-11-26 15:06:17 -05:00
Deven 7d6e8b17c9 Create README - LeetHub 2025-11-26 15:06:16 -05:00
Deven caf02f8a51 Time: 22 ms (21.01%), Space: 22.7 MB (24.41%) - LeetHub 2025-11-26 14:41:31 -05:00
Deven 6279b72065 Create README - LeetHub 2025-11-26 14:41:30 -05:00
Deven afdd2ae59f Time: 3 ms (71.33%), Space: 18.6 MB (17.59%) - LeetHub 2025-11-26 14:30:06 -05:00
Deven 3399d5f921 Time: 0 ms (100%), Space: 18.6 MB (17.59%) - LeetHub 2025-11-26 14:24:59 -05:00
Deven f6089b1e84 Time: 3 ms (71.33%), Space: 18.2 MB (95.28%) - LeetHub 2025-11-26 13:45:21 -05:00
Deven 7263390db0 Time: 3 ms (71.33%), Space: 18.2 MB (95.28%) - LeetHub 2025-11-26 13:43:48 -05:00
Deven 96785d35cc Create README - LeetHub 2025-11-26 13:43:48 -05:00
Deven c67336bdee Time: 1083 ms (14.78%), Space: 22.4 MB (5.02%) - LeetHub 2025-11-26 13:36:04 -05:00
Deven ff7a4d54ab Create README - LeetHub 2025-11-26 13:36:04 -05:00
46 changed files with 1934 additions and 0 deletions
@@ -0,0 +1,49 @@
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
"""
Complexities:
Time: O(n)
Space: O(1)
where n = max(len(l1), len(l2))
"""
# Addition by place value
currNode1 = l1
currNode2 = l2
sumNode = None
tailNode = None
carry = 0
placeValue = 1
# Loop through nodes until reached end of both lists
while currNode1 or currNode2:
v1 = currNode1.val if currNode1 else 0
v2 = currNode2.val if currNode2 else 0
sumVal = (v1 + v2 + carry) * placeValue
val = sumVal % 10
carry = sumVal // 10
newNode = ListNode(val)
if sumNode == None:
sumNode = newNode
else:
tailNode.next = newNode
tailNode = newNode
currNode1 = currNode1.next if currNode1 else None
currNode2 = currNode2.next if currNode2 else None
if carry:
tailNode.next = ListNode(carry)
return sumNode or ListNode(0)
+35
View File
@@ -0,0 +1,35 @@
<h2><a href="https://leetcode.com/problems/add-two-numbers">2. Add Two Numbers</a></h2><h3>Medium</h3><hr><p>You are given two <strong>non-empty</strong> linked lists representing two non-negative integers. The digits are stored in <strong>reverse order</strong>, and each of their nodes contains a single digit. Add the two numbers and return the sum&nbsp;as a linked list.</p>
<p>You may assume the two numbers do not contain any leading zero, except the number 0 itself.</p>
<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<img alt="" src="https://assets.leetcode.com/uploads/2020/10/02/addtwonumber1.jpg" style="width: 483px; height: 342px;" />
<pre>
<strong>Input:</strong> l1 = [2,4,3], l2 = [5,6,4]
<strong>Output:</strong> [7,0,8]
<strong>Explanation:</strong> 342 + 465 = 807.
</pre>
<p><strong class="example">Example 2:</strong></p>
<pre>
<strong>Input:</strong> l1 = [0], l2 = [0]
<strong>Output:</strong> [0]
</pre>
<p><strong class="example">Example 3:</strong></p>
<pre>
<strong>Input:</strong> l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
<strong>Output:</strong> [8,9,9,9,0,0,0,1]
</pre>
<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>
<ul>
<li>The number of nodes in each linked list is in the range <code>[1, 100]</code>.</li>
<li><code>0 &lt;= Node.val &lt;= 9</code></li>
<li>It is guaranteed that the list represents a number that does not have leading zeros.</li>
</ul>
@@ -0,0 +1,40 @@
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
"""
Complexities:
Time: O(n)
Space: O(X)
where n = len(s)
X = len([All compatible characters])
"""
charsInSubstring = set({})
startIndex = 0 # inclusive
endIndex = 0 # exclusive
maxLengthFound = 0
# Use sliding window to find solution
# - O(n) -> startIndex or endIndex always increase by 1 every iteration = 2n
while endIndex < len(s):
# if next letter not in substring, then endIndex++
if s[endIndex] not in charsInSubstring:
charsInSubstring.add(s[endIndex])
endIndex += 1
# Update maxLengthFound
if endIndex - startIndex > maxLengthFound:
maxLengthFound = endIndex - startIndex
# else pop off front until popped [next letter]
else:
while s[startIndex] != s[endIndex]:
charsInSubstring.remove(s[startIndex])
startIndex += 1
charsInSubstring.remove(s[startIndex])
startIndex += 1
return maxLengthFound
@@ -0,0 +1,35 @@
<h2><a href="https://leetcode.com/problems/longest-substring-without-repeating-characters">3. Longest Substring Without Repeating Characters</a></h2><h3>Medium</h3><hr><p>Given a string <code>s</code>, find the length of the <strong>longest</strong> <span data-keyword="substring-nonempty"><strong>substring</strong></span> without duplicate characters.</p>
<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<pre>
<strong>Input:</strong> s = &quot;abcabcbb&quot;
<strong>Output:</strong> 3
<strong>Explanation:</strong> The answer is &quot;abc&quot;, with the length of 3. Note that <code>&quot;bca&quot;</code> and <code>&quot;cab&quot;</code> are also correct answers.
</pre>
<p><strong class="example">Example 2:</strong></p>
<pre>
<strong>Input:</strong> s = &quot;bbbbb&quot;
<strong>Output:</strong> 1
<strong>Explanation:</strong> The answer is &quot;b&quot;, with the length of 1.
</pre>
<p><strong class="example">Example 3:</strong></p>
<pre>
<strong>Input:</strong> s = &quot;pwwkew&quot;
<strong>Output:</strong> 3
<strong>Explanation:</strong> The answer is &quot;wke&quot;, with the length of 3.
Notice that the answer must be a substring, &quot;pwke&quot; is a subsequence and not a substring.
</pre>
<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>
<ul>
<li><code>0 &lt;= s.length &lt;= 5 * 10<sup>4</sup></code></li>
<li><code>s</code> consists of English letters, digits, symbols and spaces.</li>
</ul>
@@ -0,0 +1,41 @@
class Solution:
def longestPalindrome(self, s: str) -> str:
"""
Complexities:
Time: O(n^2)
Space: O(1)
where n = len(s)
"""
# Returns the longest palindrome centered at s[i] or (s[i], s[i + 1])
# - O(n)
def longestPalindromeFromCenter(i: int, evenCentered: bool):
offset = 1
evenOffset = 1 if evenCentered else 0
while i - offset >= 0 and i + offset + evenOffset < len(s) and s[i - offset] == s[i + offset + evenOffset]:
offset += 1
offset -= 1 # Account for off-by-one
return s[i - offset : i + offset + evenOffset + 1]
maxPalindrome = s[0]
# For each letter, check if it is the center of a palindrome (or center with s[i+1])
# - O(n^2) = n * 2(O(n))
for i in range(len(s)):
# Check for an even length palindrome
if i + 1 < len(s) and s[i] == s[i+1]:
evenPalindrome = longestPalindromeFromCenter(i, True)
if len(evenPalindrome) > len(maxPalindrome):
maxPalindrome = evenPalindrome
oddPalindrome = longestPalindromeFromCenter(i, False)
if len(oddPalindrome) > len(maxPalindrome):
maxPalindrome = oddPalindrome
return maxPalindrome
@@ -0,0 +1,25 @@
<h2><a href="https://leetcode.com/problems/longest-palindromic-substring">5. Longest Palindromic Substring</a></h2><h3>Medium</h3><hr><p>Given a string <code>s</code>, return <em>the longest</em> <span data-keyword="palindromic-string"><em>palindromic</em></span> <span data-keyword="substring-nonempty"><em>substring</em></span> in <code>s</code>.</p>
<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<pre>
<strong>Input:</strong> s = &quot;babad&quot;
<strong>Output:</strong> &quot;bab&quot;
<strong>Explanation:</strong> &quot;aba&quot; is also a valid answer.
</pre>
<p><strong class="example">Example 2:</strong></p>
<pre>
<strong>Input:</strong> s = &quot;cbbd&quot;
<strong>Output:</strong> &quot;bb&quot;
</pre>
<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>
<ul>
<li><code>1 &lt;= s.length &lt;= 1000</code></li>
<li><code>s</code> consist of only digits and English letters.</li>
</ul>
+54
View File
@@ -0,0 +1,54 @@
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
# store frequency counts O(n)
frequencies = {}
for num in nums:
frequencies[num] = frequencies.get(num, 0) + 1
# find all pairs O(n^2)
tripleSet = set()
def addTriple(x,y,z): # O(1) *sort always on 3 items
triple = [x, y, z]
triple.sort()
tripleSet.add(tuple(triple))
freq_keys = list(frequencies.keys())
for i in range(len(freq_keys)):
for j in range(i, len(freq_keys)):
if i == j and frequencies[freq_keys[i]] < 2:
continue
pair = [freq_keys[i], freq_keys[j]]
needed = -(pair[0] + pair[1])
# - check for third in frequency counts O(1)
if frequencies.get(needed, -1) == -1:
# no triple for given pair
continue
elif needed == pair[0] or needed == pair[1]:
if pair[0] == pair[1]:
if frequencies[needed] > 2:
addTriple(pair[0], pair[1], needed)
elif frequencies[needed] > 1:
addTriple(pair[0], pair[1], needed)
else:
addTriple(pair[0], pair[1], needed)
return list(map(lambda tup: list(tup), tripleSet))
"""
O(n^3) *too slow
triples = set()
for i in range(len(nums)):
for j in range(i + 1, len(nums)):
for k in range(j + 1, len(nums)):
if nums[i] + nums[j] + nums[k] == 0:
t = [nums[i], nums[j], nums[k]]
t.sort()
triples.add(tuple(t))
return list(map(lambda tup: list(tup), triples))
"""
+41
View File
@@ -0,0 +1,41 @@
<h2><a href="https://leetcode.com/problems/3sum">15. 3Sum</a></h2><h3>Medium</h3><hr><p>Given an integer array nums, return all the triplets <code>[nums[i], nums[j], nums[k]]</code> such that <code>i != j</code>, <code>i != k</code>, and <code>j != k</code>, and <code>nums[i] + nums[j] + nums[k] == 0</code>.</p>
<p>Notice that the solution set must not contain duplicate triplets.</p>
<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<pre>
<strong>Input:</strong> nums = [-1,0,1,2,-1,-4]
<strong>Output:</strong> [[-1,-1,2],[-1,0,1]]
<strong>Explanation:</strong>
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0.
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0.
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0.
The distinct triplets are [-1,0,1] and [-1,-1,2].
Notice that the order of the output and the order of the triplets does not matter.
</pre>
<p><strong class="example">Example 2:</strong></p>
<pre>
<strong>Input:</strong> nums = [0,1,1]
<strong>Output:</strong> []
<strong>Explanation:</strong> The only possible triplet does not sum up to 0.
</pre>
<p><strong class="example">Example 3:</strong></p>
<pre>
<strong>Input:</strong> nums = [0,0,0]
<strong>Output:</strong> [[0,0,0]]
<strong>Explanation:</strong> The only possible triplet sums up to 0.
</pre>
<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>
<ul>
<li><code>3 &lt;= nums.length &lt;= 3000</code></li>
<li><code>-10<sup>5</sup> &lt;= nums[i] &lt;= 10<sup>5</sup></code></li>
</ul>
@@ -0,0 +1,68 @@
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseKGroup(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
if k == 1:
return head
dummyHead = ListNode(-1, head)
beforeSeg = dummyHead
firstInSeg = head
lastInSeg = None
afterSeg = None
# Get initial values for lastInSeg and afterSeg
curr = head
for i in range(k):
if i == k - 1:
lastInSeg = curr
afterSeg = curr.next
elif curr is None:
return head
curr = curr.next
# hold one before segment
# hold last in segment
# hold one after segment
while lastInSeg is not None:
# in segment, flip all links
prev = None
curr = beforeSeg.next
next = beforeSeg.next.next
for i in range(k):
newPrev = curr
newCurr = next
newNext = next.next if next is not None else None
curr.next = prev
prev, curr, next = newPrev, newCurr, newNext
beforeSeg.next = lastInSeg
firstInSeg.next = afterSeg
beforeSeg = firstInSeg
firstInSeg = afterSeg
curr = firstInSeg
lastInSeg = None
afterSeg = None
for i in range(k):
if curr is None:
break
elif i == k - 1:
lastInSeg = curr
afterSeg = curr.next
curr = curr.next
return dummyHead.next
+32
View File
@@ -0,0 +1,32 @@
<h2><a href="https://leetcode.com/problems/reverse-nodes-in-k-group">25. Reverse Nodes in k-Group</a></h2><h3>Hard</h3><hr><p>Given the <code>head</code> of a linked list, reverse the nodes of the list <code>k</code> at a time, and return <em>the modified list</em>.</p>
<p><code>k</code> is a positive integer and is less than or equal to the length of the linked list. If the number of nodes is not a multiple of <code>k</code> then left-out nodes, in the end, should remain as it is.</p>
<p>You may not alter the values in the list&#39;s nodes, only nodes themselves may be changed.</p>
<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<img alt="" src="https://assets.leetcode.com/uploads/2020/10/03/reverse_ex1.jpg" style="width: 542px; height: 222px;" />
<pre>
<strong>Input:</strong> head = [1,2,3,4,5], k = 2
<strong>Output:</strong> [2,1,4,3,5]
</pre>
<p><strong class="example">Example 2:</strong></p>
<img alt="" src="https://assets.leetcode.com/uploads/2020/10/03/reverse_ex2.jpg" style="width: 542px; height: 222px;" />
<pre>
<strong>Input:</strong> head = [1,2,3,4,5], k = 3
<strong>Output:</strong> [3,2,1,4,5]
</pre>
<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>
<ul>
<li>The number of nodes in the list is <code>n</code>.</li>
<li><code>1 &lt;= k &lt;= n &lt;= 5000</code></li>
<li><code>0 &lt;= Node.val &lt;= 1000</code></li>
</ul>
<p>&nbsp;</p>
<p><strong>Follow-up:</strong> Can you solve the problem in <code>O(1)</code> extra memory space?</p>
+33
View File
@@ -0,0 +1,33 @@
class Solution:
def countAndSay(self, n: int) -> str:
"""
Complexities:
Time: O(n2^n)
Space: O()
"""
# O(len(s)) where len(s) ~ O(2^n)
def RLE(s: str) -> str:
rle = ""
checkChar = s[0]
charCount = 0
for i, l in enumerate(s):
if checkChar == l:
charCount += 1
else:
rle += f"{charCount}{checkChar}"
checkChar = l
charCount = 1
if checkChar:
rle += f"{charCount}{checkChar}"
return rle
lastSol = "1"
# Iteratively call RLE on lastSol (equiv. to countAndSay(n-1))
# - O(n2^n) = n * O(2^n)
for i in range(2, n + 1):
lastSol = RLE(lastSol)
return lastSol
+50
View File
@@ -0,0 +1,50 @@
<h2><a href="https://leetcode.com/problems/count-and-say">38. Count and Say</a></h2><h3>Medium</h3><hr><p>The <strong>count-and-say</strong> sequence is a sequence of digit strings defined by the recursive formula:</p>
<ul>
<li><code>countAndSay(1) = &quot;1&quot;</code></li>
<li><code>countAndSay(n)</code> is the run-length encoding of <code>countAndSay(n - 1)</code>.</li>
</ul>
<p><a href="http://en.wikipedia.org/wiki/Run-length_encoding" target="_blank">Run-length encoding</a> (RLE) is a string compression method that works by replacing consecutive identical characters (repeated 2 or more times) with the concatenation of the character and the number marking the count of the characters (length of the run). For example, to compress the string <code>&quot;3322251&quot;</code> we replace <code>&quot;33&quot;</code> with <code>&quot;23&quot;</code>, replace <code>&quot;222&quot;</code> with <code>&quot;32&quot;</code>, replace <code>&quot;5&quot;</code> with <code>&quot;15&quot;</code> and replace <code>&quot;1&quot;</code> with <code>&quot;11&quot;</code>. Thus the compressed string becomes <code>&quot;23321511&quot;</code>.</p>
<p>Given a positive integer <code>n</code>, return <em>the </em><code>n<sup>th</sup></code><em> element of the <strong>count-and-say</strong> sequence</em>.</p>
<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<div class="example-block">
<p><strong>Input:</strong> <span class="example-io">n = 4</span></p>
<p><strong>Output:</strong> <span class="example-io">&quot;1211&quot;</span></p>
<p><strong>Explanation:</strong></p>
<pre>
countAndSay(1) = &quot;1&quot;
countAndSay(2) = RLE of &quot;1&quot; = &quot;11&quot;
countAndSay(3) = RLE of &quot;11&quot; = &quot;21&quot;
countAndSay(4) = RLE of &quot;21&quot; = &quot;1211&quot;
</pre>
</div>
<p><strong class="example">Example 2:</strong></p>
<div class="example-block">
<p><strong>Input:</strong> <span class="example-io">n = 1</span></p>
<p><strong>Output:</strong> <span class="example-io">&quot;1&quot;</span></p>
<p><strong>Explanation:</strong></p>
<p>This is the base case.</p>
</div>
<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>
<ul>
<li><code>1 &lt;= n &lt;= 30</code></li>
</ul>
<p>&nbsp;</p>
<strong>Follow up:</strong> Could you solve it iteratively?
@@ -0,0 +1,31 @@
class Solution:
def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
"""
Complexities
Time: O(Mn)
Space: O(n)
where n = len(strs)
M = max(len(str[i])
"""
# Store strs in dictionary, keyed by sorted string (or frequency count)
strsByAnagram = dict({})
# Conversion helper - O(M)
def toFreqTuple(s: str):
freq = [0] * 26
for l in s:
letter_index = ord(l) - ord('a')
freq[letter_index] += 1
return tuple(freq)
# Map each s in str to its key - O(Mn)
for s in strs:
key = toFreqTuple(s)
strsByAnagram[key] = [*strsByAnagram.get(key, []), s]
# Convert dict to array to return - O(n)
return list(strsByAnagram.values())
+43
View File
@@ -0,0 +1,43 @@
<h2><a href="https://leetcode.com/problems/group-anagrams">49. Group Anagrams</a></h2><h3>Medium</h3><hr><p>Given an array of strings <code>strs</code>, group the <span data-keyword="anagram">anagrams</span> together. You can return the answer in <strong>any order</strong>.</p>
<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<div class="example-block">
<p><strong>Input:</strong> <span class="example-io">strs = [&quot;eat&quot;,&quot;tea&quot;,&quot;tan&quot;,&quot;ate&quot;,&quot;nat&quot;,&quot;bat&quot;]</span></p>
<p><strong>Output:</strong> <span class="example-io">[[&quot;bat&quot;],[&quot;nat&quot;,&quot;tan&quot;],[&quot;ate&quot;,&quot;eat&quot;,&quot;tea&quot;]]</span></p>
<p><strong>Explanation:</strong></p>
<ul>
<li>There is no string in strs that can be rearranged to form <code>&quot;bat&quot;</code>.</li>
<li>The strings <code>&quot;nat&quot;</code> and <code>&quot;tan&quot;</code> are anagrams as they can be rearranged to form each other.</li>
<li>The strings <code>&quot;ate&quot;</code>, <code>&quot;eat&quot;</code>, and <code>&quot;tea&quot;</code> are anagrams as they can be rearranged to form each other.</li>
</ul>
</div>
<p><strong class="example">Example 2:</strong></p>
<div class="example-block">
<p><strong>Input:</strong> <span class="example-io">strs = [&quot;&quot;]</span></p>
<p><strong>Output:</strong> <span class="example-io">[[&quot;&quot;]]</span></p>
</div>
<p><strong class="example">Example 3:</strong></p>
<div class="example-block">
<p><strong>Input:</strong> <span class="example-io">strs = [&quot;a&quot;]</span></p>
<p><strong>Output:</strong> <span class="example-io">[[&quot;a&quot;]]</span></p>
</div>
<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>
<ul>
<li><code>1 &lt;= strs.length &lt;= 10<sup>4</sup></code></li>
<li><code>0 &lt;= strs[i].length &lt;= 100</code></li>
<li><code>strs[i]</code> consists of lowercase English letters.</li>
</ul>
@@ -0,0 +1,63 @@
class Solution:
def setZeroes(self, matrix: List[List[int]]) -> None:
"""
Do not return anything, modify matrix in-place instead.
"""
# Total complexities:
# O(mn) time
# O(1) space
# Prepare first row/col for marking
firstEntry = matrix[0][0]
# - use m[0][0] as indicator for first row and col
NO_ZEROES_IN_FIRST_ROW_OR_COL = 1
ZERO_IN_FIRST_ROW = 2
ZERO_IN_FIRST_COL = 3
ZERO_IN_FIRST_ROW_AND_COL = 4
matrix[0][0] = NO_ZEROES_IN_FIRST_ROW_OR_COL
if firstEntry == 0:
matrix[0][0] = ZERO_IN_FIRST_ROW_AND_COL
else:
print(f"cp0")
# Search first col for 0s - O(n)
for i in range(1, len(matrix)):
print(f"cp1")
if matrix[i][0] == 0:
matrix[0][0] = ZERO_IN_FIRST_COL
break
# Search first row for 0s - O(m)
for j in range(1, len(matrix[0])):
if matrix[0][j] == 0:
if matrix[0][0] == ZERO_IN_FIRST_COL:
matrix[0][0] = ZERO_IN_FIRST_ROW_AND_COL
else:
matrix[0][0] = ZERO_IN_FIRST_ROW
break
# Find all zeros outside the first row/col - O(mn)
for i in range(1, len(matrix)):
for j in range(1, len(matrix[i])):
if matrix[i][j] == 0:
# Use the first row/col as markers
matrix[i][0] = 0
matrix[0][j] = 0
# Zero center as needed - O(mn)
for i in range(1, len(matrix)):
for j in range(1, len(matrix[i])):
if matrix[i][0] == 0 or matrix[0][j] == 0:
matrix[i][j] = 0
# Set first row/col if needed
if matrix[0][0] == ZERO_IN_FIRST_ROW or matrix[0][0] == ZERO_IN_FIRST_ROW_AND_COL:
for j in range(1, len(matrix[0])):
matrix[0][j] = 0
if matrix[0][0] == ZERO_IN_FIRST_COL or matrix[0][0] == ZERO_IN_FIRST_ROW_AND_COL:
for i in range(1, len(matrix)):
matrix[i][0] = 0
matrix[0][0] = firstEntry if matrix[0][0] == NO_ZEROES_IN_FIRST_ROW_OR_COL else 0
+37
View File
@@ -0,0 +1,37 @@
<h2><a href="https://leetcode.com/problems/set-matrix-zeroes">73. Set Matrix Zeroes</a></h2><h3>Medium</h3><hr><p>Given an <code>m x n</code> integer matrix <code>matrix</code>, if an element is <code>0</code>, set its entire row and column to <code>0</code>&#39;s.</p>
<p>You must do it <a href="https://en.wikipedia.org/wiki/In-place_algorithm" target="_blank">in place</a>.</p>
<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<img alt="" src="https://assets.leetcode.com/uploads/2020/08/17/mat1.jpg" style="width: 450px; height: 169px;" />
<pre>
<strong>Input:</strong> matrix = [[1,1,1],[1,0,1],[1,1,1]]
<strong>Output:</strong> [[1,0,1],[0,0,0],[1,0,1]]
</pre>
<p><strong class="example">Example 2:</strong></p>
<img alt="" src="https://assets.leetcode.com/uploads/2020/08/17/mat2.jpg" style="width: 450px; height: 137px;" />
<pre>
<strong>Input:</strong> matrix = [[0,1,2,0],[3,4,5,2],[1,3,1,5]]
<strong>Output:</strong> [[0,0,0,0],[0,4,5,0],[0,3,1,0]]
</pre>
<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>
<ul>
<li><code>m == matrix.length</code></li>
<li><code>n == matrix[0].length</code></li>
<li><code>1 &lt;= m, n &lt;= 200</code></li>
<li><code>-2<sup>31</sup> &lt;= matrix[i][j] &lt;= 2<sup>31</sup> - 1</code></li>
</ul>
<p>&nbsp;</p>
<p><strong>Follow up:</strong></p>
<ul>
<li>A straightforward solution using <code>O(mn)</code> space is probably a bad idea.</li>
<li>A simple improvement uses <code>O(m + n)</code> space, but still not the best solution.</li>
<li>Could you devise a constant space solution?</li>
</ul>
@@ -0,0 +1,29 @@
# 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 inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
"""
Complexities:
Time: O(n)
Space: O(n)
where n = total node in graph
"""
if not root:
return []
arr = []
if root.left:
arr += self.inorderTraversal(root.left)
arr += [root.val]
if root.right:
arr += self.inorderTraversal(root.right)
return arr
@@ -0,0 +1,53 @@
<h2><a href="https://leetcode.com/problems/binary-tree-inorder-traversal">94. Binary Tree Inorder Traversal</a></h2><h3>Easy</h3><hr><p>Given the <code>root</code> of a binary tree, return <em>the inorder traversal of its nodes&#39; values</em>.</p>
<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<div class="example-block">
<p><strong>Input:</strong> <span class="example-io">root = [1,null,2,3]</span></p>
<p><strong>Output:</strong> <span class="example-io">[1,3,2]</span></p>
<p><strong>Explanation:</strong></p>
<p><img alt="" src="https://assets.leetcode.com/uploads/2024/08/29/screenshot-2024-08-29-202743.png" style="width: 200px; height: 264px;" /></p>
</div>
<p><strong class="example">Example 2:</strong></p>
<div class="example-block">
<p><strong>Input:</strong> <span class="example-io">root = [1,2,3,4,5,null,8,null,null,6,7,9]</span></p>
<p><strong>Output:</strong> <span class="example-io">[4,2,6,5,7,1,3,9,8]</span></p>
<p><strong>Explanation:</strong></p>
<p><img alt="" src="https://assets.leetcode.com/uploads/2024/08/29/tree_2.png" style="width: 350px; height: 286px;" /></p>
</div>
<p><strong class="example">Example 3:</strong></p>
<div class="example-block">
<p><strong>Input:</strong> <span class="example-io">root = []</span></p>
<p><strong>Output:</strong> <span class="example-io">[]</span></p>
</div>
<p><strong class="example">Example 4:</strong></p>
<div class="example-block">
<p><strong>Input:</strong> <span class="example-io">root = [1]</span></p>
<p><strong>Output:</strong> <span class="example-io">[1]</span></p>
</div>
<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>
<ul>
<li>The number of nodes in the tree is in the range <code>[0, 100]</code>.</li>
<li><code>-100 &lt;= Node.val &lt;= 100</code></li>
</ul>
<p>&nbsp;</p>
<strong>Follow up:</strong> Recursive solution is trivial, could you do it iteratively?
@@ -0,0 +1,58 @@
# 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 zigzagLevelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
"""
Complexities:
Time: O(n)
Space: O(n)
where n = number of nodes in graph
"""
if not root:
return []
traversal = [[root]]
hasNextLevel = root.left or root.right
# Store nodes from left to right in arrays by depth - O(n)
while hasNextLevel:
lastLevel = traversal[-1]
nextLevel = []
hasNextLevel = False
for node in lastLevel:
if node.left:
nextLevel.append(node.left)
hasNextLevel = hasNextLevel or bool(node.left.left or node.left.right)
if node.right:
nextLevel.append(node.right)
hasNextLevel = hasNextLevel or bool(node.right.left or node.right.right)
traversal.append(nextLevel)
# Convert nodes to values + reverse every other level - O(n)
valueTraversal = []
for depth, level in enumerate(traversal):
start = 0 if depth % 2 == 0 else len(level) - 1
end = len(level) if depth % 2 == 0 else -1
step = 1 if depth % 2 == 0 else -1
nextLevelValues = []
for i in range(start, end, step):
nextLevelValues.append(level[i].val)
valueTraversal.append(nextLevelValues)
return valueTraversal
@@ -0,0 +1,31 @@
<h2><a href="https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal">103. Binary Tree Zigzag Level Order Traversal</a></h2><h3>Medium</h3><hr><p>Given the <code>root</code> of a binary tree, return <em>the zigzag level order traversal of its nodes&#39; values</em>. (i.e., from left to right, then right to left for the next level and alternate between).</p>
<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<img alt="" src="https://assets.leetcode.com/uploads/2021/02/19/tree1.jpg" style="width: 277px; height: 302px;" />
<pre>
<strong>Input:</strong> root = [3,9,20,null,null,15,7]
<strong>Output:</strong> [[3],[20,9],[15,7]]
</pre>
<p><strong class="example">Example 2:</strong></p>
<pre>
<strong>Input:</strong> root = [1]
<strong>Output:</strong> [[1]]
</pre>
<p><strong class="example">Example 3:</strong></p>
<pre>
<strong>Input:</strong> root = []
<strong>Output:</strong> []
</pre>
<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>
<ul>
<li>The number of nodes in the tree is in the range <code>[0, 2000]</code>.</li>
<li><code>-100 &lt;= Node.val &lt;= 100</code></li>
</ul>
+31
View File
@@ -0,0 +1,31 @@
"""
# Definition for a Node.
class Node:
def __init__(self, val = 0, neighbors = None):
self.val = val
self.neighbors = neighbors if neighbors is not None else []
"""
from typing import Optional
from collections import deque
class Solution:
def cloneGraph(self, node: Optional['Node']) -> Optional['Node']:
if not node:
return node
newHead = Node(node.val)
frontier = deque([ node ])
nodeMapping = { node.val: newHead }
while len(frontier) > 0:
current = frontier.popleft()
for n in current.neighbors:
if n.val not in nodeMapping:
newNode = Node(n.val)
nodeMapping[newNode.val] = newNode
frontier.append(n)
nodeMapping[current.val].neighbors.append(nodeMapping[n.val])
return newHead
+62
View File
@@ -0,0 +1,62 @@
<h2><a href="https://leetcode.com/problems/clone-graph">133. Clone Graph</a></h2><h3>Medium</h3><hr><p>Given a reference of a node in a <strong><a href="https://en.wikipedia.org/wiki/Connectivity_(graph_theory)#Connected_graph" target="_blank">connected</a></strong> undirected graph.</p>
<p>Return a <a href="https://en.wikipedia.org/wiki/Object_copying#Deep_copy" target="_blank"><strong>deep copy</strong></a> (clone) of the graph.</p>
<p>Each node in the graph contains a value (<code>int</code>) and a list (<code>List[Node]</code>) of its neighbors.</p>
<pre>
class Node {
public int val;
public List&lt;Node&gt; neighbors;
}
</pre>
<p>&nbsp;</p>
<p><strong>Test case format:</strong></p>
<p>For simplicity, each node&#39;s value is the same as the node&#39;s index (1-indexed). For example, the first node with <code>val == 1</code>, the second node with <code>val == 2</code>, and so on. The graph is represented in the test case using an adjacency list.</p>
<p><b>An adjacency list</b> is a collection of unordered <b>lists</b> used to represent a finite graph. Each list describes the set of neighbors of a node in the graph.</p>
<p>The given node will always be the first node with <code>val = 1</code>. You must return the <strong>copy of the given node</strong> as a reference to the cloned graph.</p>
<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<img alt="" src="https://assets.leetcode.com/uploads/2019/11/04/133_clone_graph_question.png" style="width: 454px; height: 500px;" />
<pre>
<strong>Input:</strong> adjList = [[2,4],[1,3],[2,4],[1,3]]
<strong>Output:</strong> [[2,4],[1,3],[2,4],[1,3]]
<strong>Explanation:</strong> There are 4 nodes in the graph.
1st node (val = 1)&#39;s neighbors are 2nd node (val = 2) and 4th node (val = 4).
2nd node (val = 2)&#39;s neighbors are 1st node (val = 1) and 3rd node (val = 3).
3rd node (val = 3)&#39;s neighbors are 2nd node (val = 2) and 4th node (val = 4).
4th node (val = 4)&#39;s neighbors are 1st node (val = 1) and 3rd node (val = 3).
</pre>
<p><strong class="example">Example 2:</strong></p>
<img alt="" src="https://assets.leetcode.com/uploads/2020/01/07/graph.png" style="width: 163px; height: 148px;" />
<pre>
<strong>Input:</strong> adjList = [[]]
<strong>Output:</strong> [[]]
<strong>Explanation:</strong> 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.
</pre>
<p><strong class="example">Example 3:</strong></p>
<pre>
<strong>Input:</strong> adjList = []
<strong>Output:</strong> []
<strong>Explanation:</strong> This an empty graph, it does not have any nodes.
</pre>
<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>
<ul>
<li>The number of nodes in the graph is in the range <code>[0, 100]</code>.</li>
<li><code>1 &lt;= Node.val &lt;= 100</code></li>
<li><code>Node.val</code> is unique for each node.</li>
<li>There are no repeated edges and no self-loops in the graph.</li>
<li>The Graph is connected and all nodes can be visited starting from the given node.</li>
</ul>
@@ -0,0 +1,19 @@
import heapq
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
heap = nums[:k]
# Heapify (min) the first k elements
heapq.heapify(heap)
# iterate over k+1...n - O(n) times
# - if larger than min in heap, replace min - O(log k)
# - else do nothing
for i in range(k, len(nums)):
num = nums[i]
if num > heap[0]:
heapq.heapreplace(heap, num)
# return min in heap
return heap[0]
@@ -0,0 +1,21 @@
<h2><a href="https://leetcode.com/problems/kth-largest-element-in-an-array">215. Kth Largest Element in an Array</a></h2><h3>Medium</h3><hr><p>Given an integer array <code>nums</code> and an integer <code>k</code>, return <em>the</em> <code>k<sup>th</sup></code> <em>largest element in the array</em>.</p>
<p>Note that it is the <code>k<sup>th</sup></code> largest element in the sorted order, not the <code>k<sup>th</sup></code> distinct element.</p>
<p>Can you solve it without sorting?</p>
<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<pre><strong>Input:</strong> nums = [3,2,1,5,6,4], k = 2
<strong>Output:</strong> 5
</pre><p><strong class="example">Example 2:</strong></p>
<pre><strong>Input:</strong> nums = [3,2,3,1,2,4,5,5,6], k = 4
<strong>Output:</strong> 4
</pre>
<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>
<ul>
<li><code>1 &lt;= k &lt;= nums.length &lt;= 10<sup>5</sup></code></li>
<li><code>-10<sup>4</sup> &lt;= nums[i] &lt;= 10<sup>4</sup></code></li>
</ul>
@@ -0,0 +1,60 @@
class Solution:
def calculate(self, s: str) -> int:
"""
Complexities:
Time: O(n)
Space: O(n)
where n = len(s)
"""
numbers = "0123456789"
# Read from left to right: save in stack (full number or operator)
# - save number
# - on operator:
# -- if * or /, evaluate
# -- if + or -, wait and continue
currentNumber = 0
stack = []
# Evaluate numbers and create stack (of additions + subtractions)
for c in s + "\0":
if c == " ":
continue
elif c in numbers:
digit = int(c)
currentNumber = (currentNumber * 10) + digit
else:
stack.append(currentNumber)
currentNumber = 0
if len(stack) >= 3 and stack[-2] in "*/":
rOperand = stack.pop()
operator = stack.pop()
lOperand = stack.pop()
if operator == "*":
stack.append(lOperand * rOperand)
elif operator == "/":
stack.append(int(lOperand / rOperand))
stack.append(c)
# Pop off null terminator
stack.pop()
# Evaluate all additions and subtractions from stack
current = stack[0]
for i in range(1, len(stack) - 1, 2):
operator = stack[i]
rOperand = stack[i + 1]
if operator == "+":
current += rOperand
elif operator == "-":
current -= rOperand
return current
+29
View File
@@ -0,0 +1,29 @@
<h2><a href="https://leetcode.com/problems/basic-calculator-ii">227. Basic Calculator II</a></h2><h3>Medium</h3><hr><p>Given a string <code>s</code> which represents an expression, <em>evaluate this expression and return its value</em>.&nbsp;</p>
<p>The integer division should truncate toward zero.</p>
<p>You may assume that the given expression is always valid. All intermediate results will be in the range of <code>[-2<sup>31</sup>, 2<sup>31</sup> - 1]</code>.</p>
<p><strong>Note:</strong> You are not allowed to use any built-in function which evaluates strings as mathematical expressions, such as <code>eval()</code>.</p>
<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<pre><strong>Input:</strong> s = "3+2*2"
<strong>Output:</strong> 7
</pre><p><strong class="example">Example 2:</strong></p>
<pre><strong>Input:</strong> s = " 3/2 "
<strong>Output:</strong> 1
</pre><p><strong class="example">Example 3:</strong></p>
<pre><strong>Input:</strong> s = " 3+5 / 2 "
<strong>Output:</strong> 5
</pre>
<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>
<ul>
<li><code>1 &lt;= s.length &lt;= 3 * 10<sup>5</sup></code></li>
<li><code>s</code> consists of integers and operators <code>(&#39;+&#39;, &#39;-&#39;, &#39;*&#39;, &#39;/&#39;)</code> separated by some number of spaces.</li>
<li><code>s</code> represents <strong>a valid expression</strong>.</li>
<li>All the integers in the expression are non-negative integers in the range <code>[0, 2<sup>31</sup> - 1]</code>.</li>
<li>The answer is <strong>guaranteed</strong> to fit in a <strong>32-bit integer</strong>.</li>
</ul>
+24
View File
@@ -0,0 +1,24 @@
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
"""
Complexities:
Time: O(mn)
Space: O(m)
where n = len(coins), m = amount
"""
dp = [-1] * (amount + 1)
dp[0] = 0
for i in range(amount + 1):
for coinValue in coins:
if dp[i] == -1 or i + coinValue > amount:
continue
elif dp[i + coinValue] == -1:
dp[i + coinValue] = dp[i] + 1
else:
dp[i + coinValue] = min(dp[i + coinValue], dp[i] + 1)
print(dp)
return dp[amount]
+37
View File
@@ -0,0 +1,37 @@
<h2><a href="https://leetcode.com/problems/coin-change">322. Coin Change</a></h2><h3>Medium</h3><hr><p>You are given an integer array <code>coins</code> representing coins of different denominations and an integer <code>amount</code> representing a total amount of money.</p>
<p>Return <em>the fewest number of coins that you need to make up that amount</em>. If that amount of money cannot be made up by any combination of the coins, return <code>-1</code>.</p>
<p>You may assume that you have an infinite number of each kind of coin.</p>
<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<pre>
<strong>Input:</strong> coins = [1,2,5], amount = 11
<strong>Output:</strong> 3
<strong>Explanation:</strong> 11 = 5 + 5 + 1
</pre>
<p><strong class="example">Example 2:</strong></p>
<pre>
<strong>Input:</strong> coins = [2], amount = 3
<strong>Output:</strong> -1
</pre>
<p><strong class="example">Example 3:</strong></p>
<pre>
<strong>Input:</strong> coins = [1], amount = 0
<strong>Output:</strong> 0
</pre>
<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>
<ul>
<li><code>1 &lt;= coins.length &lt;= 12</code></li>
<li><code>1 &lt;= coins[i] &lt;= 2<sup>31</sup> - 1</code></li>
<li><code>0 &lt;= amount &lt;= 10<sup>4</sup></code></li>
</ul>
@@ -0,0 +1,50 @@
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def oddEvenList(self, head: Optional[ListNode]) -> Optional[ListNode]:
"""
Complexities:
Time: O(n)
Space: O(1)
where n = len(head)
"""
# If len(head) <= 2, already sorted
if not head or not head.next:
return head
oddHead = head
oddTail = head
evenHead = head.next
evenTail = head.next
currNode = head.next.next
isOddIndex = True
# Set tail.next = None
oddTail.next = None
evenTail.next = None
# Separate list into odd list and even list
while currNode:
nextNode = currNode.next
currNode.next = None
if isOddIndex:
oddTail.next = currNode
oddTail = currNode
else:
evenTail.next = currNode
evenTail = currNode
currNode = nextNode
isOddIndex = not isOddIndex
# Attach both lists
oddTail.next = evenHead
return oddHead
+30
View File
@@ -0,0 +1,30 @@
<h2><a href="https://leetcode.com/problems/odd-even-linked-list">328. Odd Even Linked List</a></h2><h3>Medium</h3><hr><p>Given the <code>head</code> of a singly linked list, group all the nodes with odd indices together followed by the nodes with even indices, and return <em>the reordered list</em>.</p>
<p>The <strong>first</strong> node is considered <strong>odd</strong>, and the <strong>second</strong> node is <strong>even</strong>, and so on.</p>
<p>Note that the relative order inside both the even and odd groups should remain as it was in the input.</p>
<p>You must solve the problem&nbsp;in <code>O(1)</code>&nbsp;extra space complexity and <code>O(n)</code> time complexity.</p>
<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<img alt="" src="https://assets.leetcode.com/uploads/2021/03/10/oddeven-linked-list.jpg" style="width: 300px; height: 123px;" />
<pre>
<strong>Input:</strong> head = [1,2,3,4,5]
<strong>Output:</strong> [1,3,5,2,4]
</pre>
<p><strong class="example">Example 2:</strong></p>
<img alt="" src="https://assets.leetcode.com/uploads/2021/03/10/oddeven2-linked-list.jpg" style="width: 500px; height: 142px;" />
<pre>
<strong>Input:</strong> head = [2,1,3,5,6,4,7]
<strong>Output:</strong> [2,3,6,7,1,5,4]
</pre>
<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>
<ul>
<li>The number of nodes in the linked list is in the range <code>[0, 10<sup>4</sup>]</code>.</li>
<li><code>-10<sup>6</sup> &lt;= Node.val &lt;= 10<sup>6</sup></code></li>
</ul>
@@ -0,0 +1,37 @@
class Solution:
def increasingTriplet(self, nums: List[int]) -> bool:
"""
Complexities:
Time: O(n)
Space: O(n)
where n = len(nums)
"""
# Find j candidates (where nums[i] < nums[j])
# - j is not 0
# - nums[j] is not min so far
# --- O(n)
jCandidates = []
minSoFar = nums[0]
for j in range(1, len(nums)):
if nums[j] <= minSoFar:
minSoFar = nums[j]
else:
jCandidates.append(j)
# Fail fast: 0-1 jCandidates = no increasing tuplet (one j candidate will be k)
if len(jCandidates) <= 1:
return False
# Find k candidates (where nums[j] < nums[k])
# - do the same iteration as j but only over j candidates
# --- O(n)
minSoFar = nums[jCandidates[0]]
for kPrime in range(1, len(jCandidates)):
if nums[jCandidates[kPrime]] <= minSoFar:
minSoFar = nums[jCandidates[kPrime]]
else:
return True
return False
@@ -0,0 +1,37 @@
<h2><a href="https://leetcode.com/problems/increasing-triplet-subsequence">334. Increasing Triplet Subsequence</a></h2><h3>Medium</h3><hr><p>Given an integer array <code>nums</code>, return <code>true</code><em> if there exists a triple of indices </em><code>(i, j, k)</code><em> such that </em><code>i &lt; j &lt; k</code><em> and </em><code>nums[i] &lt; nums[j] &lt; nums[k]</code>. If no such indices exists, return <code>false</code>.</p>
<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<pre>
<strong>Input:</strong> nums = [1,2,3,4,5]
<strong>Output:</strong> true
<strong>Explanation:</strong> Any triplet where i &lt; j &lt; k is valid.
</pre>
<p><strong class="example">Example 2:</strong></p>
<pre>
<strong>Input:</strong> nums = [5,4,3,2,1]
<strong>Output:</strong> false
<strong>Explanation:</strong> No triplet exists.
</pre>
<p><strong class="example">Example 3:</strong></p>
<pre>
<strong>Input:</strong> nums = [2,1,5,0,4,6]
<strong>Output:</strong> true
<strong>Explanation:</strong> One of the valid triplet is (1, 4, 5), because nums[1] == 1 &lt; nums[4] == 4 &lt; nums[5] == 6.
</pre>
<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>
<ul>
<li><code>1 &lt;= nums.length &lt;= 5 * 10<sup>5</sup></code></li>
<li><code>-2<sup>31</sup> &lt;= nums[i] &lt;= 2<sup>31</sup> - 1</code></li>
</ul>
<p>&nbsp;</p>
<strong>Follow up:</strong> Could you implement a solution that runs in <code>O(n)</code> time complexity and <code>O(1)</code> space complexity?
+84
View File
@@ -0,0 +1,84 @@
# """
# This is the interface that allows for creating nested lists.
# You should not implement it, or speculate about its implementation
# """
#class NestedInteger:
# def __init__(self, value=None):
# """
# If value is not specified, initializes an empty list.
# Otherwise initializes a single integer equal to value.
# """
#
# def isInteger(self):
# """
# @return True if this NestedInteger holds a single integer, rather than a nested list.
# :rtype bool
# """
#
# def add(self, elem):
# """
# Set this NestedInteger to hold a nested list and adds a nested integer elem to it.
# :rtype void
# """
#
# def setInteger(self, value):
# """
# Set this NestedInteger to hold a single integer equal to value.
# :rtype void
# """
#
# def getInteger(self):
# """
# @return the single integer that this NestedInteger holds, if it holds a single integer
# Return None if this NestedInteger holds a nested list
# :rtype int
# """
#
# def getList(self):
# """
# @return the nested list that this NestedInteger holds, if it holds a nested list
# Return None if this NestedInteger holds a single integer
# :rtype List[NestedInteger]
# """
class Solution:
def deserialize(self, s: str) -> NestedInteger:
"""
Complexities:
Time: O(n)
Space: O(n)
where n = len(s)
"""
# base case: number
if s[0] != "[":
return NestedInteger(int(s))
# is a list
head = NestedInteger()
stack = [head]
i = 1
while i < len(s):
if s[i] == ",":
i += 1
elif s[i] == "[":
newNestedInteger = NestedInteger()
stack[-1].add(newNestedInteger)
stack.append(newNestedInteger)
i += 1
elif s[i] == "]":
stack.pop()
i += 1
else: # Is number or '-'
# Find entire number
j = i
while s[j] not in ",]":
j += 1
newInt = int(s[i:j])
stack[-1].add(NestedInteger(newInt))
i = j
return head
+35
View File
@@ -0,0 +1,35 @@
<h2><a href="https://leetcode.com/problems/mini-parser">385. Mini Parser</a></h2><h3>Medium</h3><hr><p>Given a string s represents the serialization of a nested list, implement a parser to deserialize it and return <em>the deserialized</em> <code>NestedInteger</code>.</p>
<p>Each element is either an integer or a list whose elements may also be integers or other lists.</p>
<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<pre>
<strong>Input:</strong> s = &quot;324&quot;
<strong>Output:</strong> 324
<strong>Explanation:</strong> You should return a NestedInteger object which contains a single integer 324.
</pre>
<p><strong class="example">Example 2:</strong></p>
<pre>
<strong>Input:</strong> s = &quot;[123,[456,[789]]]&quot;
<strong>Output:</strong> [123,[456,[789]]]
<strong>Explanation:</strong> Return a NestedInteger object containing a nested list with 2 elements:
1. An integer containing value 123.
2. A nested list containing two elements:
i. An integer containing value 456.
ii. A nested list with one element:
a. An integer containing value 789
</pre>
<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>
<ul>
<li><code>1 &lt;= s.length &lt;= 5 * 10<sup>4</sup></code></li>
<li><code>s</code> consists of digits, square brackets <code>&quot;[]&quot;</code>, negative sign <code>&#39;-&#39;</code>, and commas <code>&#39;,&#39;</code>.</li>
<li><code>s</code> is the serialization of valid <code>NestedInteger</code>.</li>
<li>All the values in the input are in the range <code>[-10<sup>6</sup>, 10<sup>6</sup>]</code>.</li>
</ul>
@@ -0,0 +1,61 @@
class Solution:
def checkValidString(self, s: str) -> bool:
"""
Complexities:
Time: O(n)
Space: O(n)
where n = len(s)
"""
bracketCount = 0
starCount = 0
starIndecies = []
usedStars = 0
# Forward pass - allocate as many *s to be (
# - when allocating a star, always use the star that appears first
for i, l in enumerate(s):
if l == '(':
bracketCount += 1
elif l == '*':
starCount += 1
starIndecies.append(i)
elif bracketCount > 0:
bracketCount -= 1
elif starCount > 0:
starCount -= 1
usedStars += 1
else:
return False
# There are already matching opening/closing brackets
# - all stars are assigned empty string
if bracketCount == 0:
return True
# There are more closed brackets needed than the amount of remaining stars
if bracketCount > 0 and bracketCount > starCount:
return False
# Backward pass - allocate as many *s to be )
# - the first `usedStars` stars are considered used from the forward pass
firstViableStar = starIndecies[usedStars]
bracketCount = 0
starCount = 0
for i in range(len(s) - 1, 0, -1):
l = s[i]
if l == ')':
bracketCount += 1
elif l == '*':
starCount += 1 if i >= firstViableStar else 0
elif bracketCount > 0:
bracketCount -= 1
elif starCount > 0:
starIndecies.pop(0)
starCount -= 1
else:
return False
return True
+29
View File
@@ -0,0 +1,29 @@
<h2><a href="https://leetcode.com/problems/valid-parenthesis-string">678. Valid Parenthesis String</a></h2><h3>Medium</h3><hr><p>Given a string <code>s</code> containing only three types of characters: <code>&#39;(&#39;</code>, <code>&#39;)&#39;</code> and <code>&#39;*&#39;</code>, return <code>true</code> <em>if</em> <code>s</code> <em>is <strong>valid</strong></em>.</p>
<p>The following rules define a <strong>valid</strong> string:</p>
<ul>
<li>Any left parenthesis <code>&#39;(&#39;</code> must have a corresponding right parenthesis <code>&#39;)&#39;</code>.</li>
<li>Any right parenthesis <code>&#39;)&#39;</code> must have a corresponding left parenthesis <code>&#39;(&#39;</code>.</li>
<li>Left parenthesis <code>&#39;(&#39;</code> must go before the corresponding right parenthesis <code>&#39;)&#39;</code>.</li>
<li><code>&#39;*&#39;</code> could be treated as a single right parenthesis <code>&#39;)&#39;</code> or a single left parenthesis <code>&#39;(&#39;</code> or an empty string <code>&quot;&quot;</code>.</li>
</ul>
<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<pre><strong>Input:</strong> s = "()"
<strong>Output:</strong> true
</pre><p><strong class="example">Example 2:</strong></p>
<pre><strong>Input:</strong> s = "(*)"
<strong>Output:</strong> true
</pre><p><strong class="example">Example 3:</strong></p>
<pre><strong>Input:</strong> s = "(*))"
<strong>Output:</strong> true
</pre>
<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>
<ul>
<li><code>1 &lt;= s.length &lt;= 100</code></li>
<li><code>s[i]</code> is <code>&#39;(&#39;</code>, <code>&#39;)&#39;</code> or <code>&#39;*&#39;</code>.</li>
</ul>
@@ -0,0 +1,37 @@
class Solution:
def asteroidCollision(self, asteroids: List[int]) -> List[int]:
"""
Complexities:
Time: O(n)
Space: O(n)
where n = len(asteroids)
"""
# iterate left to right
# - if right (+ve), keep stack
# - if left (-ve), compare/consume top of stack
# - - if left consume all of stack, add to output (it will survive)
stack = []
survivedAsteroids = []
for i in range(len(asteroids)):
if asteroids[i] > 0:
stack.append(asteroids[i])
else:
isDestroyed = False
while len(stack) > 0 and abs(asteroids[i]) >= stack[-1]:
if abs(asteroids[i]) == stack[-1]:
isDestroyed = True
stack.pop()
break
stack.pop()
if len(stack) == 0 and not isDestroyed:
survivedAsteroids.append(asteroids[i])
# also return stack
survivedAsteroids += stack
return survivedAsteroids
+47
View File
@@ -0,0 +1,47 @@
<h2><a href="https://leetcode.com/problems/asteroid-collision">735. Asteroid Collision</a></h2><h3>Medium</h3><hr><p>We are given an array <code>asteroids</code> of integers representing asteroids in a row. The indices of the asteroid in the array represent their relative position in space.</p>
<p>For each asteroid, the absolute value represents its size, and the sign represents its direction (positive meaning right, negative meaning left). Each asteroid moves at the same speed.</p>
<p>Find out the state of the asteroids after all collisions. If two asteroids meet, the smaller one will explode. If both are the same size, both will explode. Two asteroids moving in the same direction will never meet.</p>
<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<pre>
<strong>Input:</strong> asteroids = [5,10,-5]
<strong>Output:</strong> [5,10]
<strong>Explanation:</strong> The 10 and -5 collide resulting in 10. The 5 and 10 never collide.
</pre>
<p><strong class="example">Example 2:</strong></p>
<pre>
<strong>Input:</strong> asteroids = [8,-8]
<strong>Output:</strong> []
<strong>Explanation:</strong> The 8 and -8 collide exploding each other.
</pre>
<p><strong class="example">Example 3:</strong></p>
<pre>
<strong>Input:</strong> asteroids = [10,2,-5]
<strong>Output:</strong> [10]
<strong>Explanation:</strong> The 2 and -5 collide resulting in -5. The 10 and -5 collide resulting in 10.
</pre>
<p><strong class="example">Example 4:</strong></p>
<pre>
<strong>Input:</strong> asteroids = [3,5,-6,2,-1,4]
<strong>Output:</strong> [-6,2,4]
<strong>Explanation:</strong> The asteroid -6 makes the asteroid 3 and 5 explode, and then continues going left. On the other side, the asteroid 2 makes the asteroid -1 explode and then continues going right, without reaching asteroid 4.
</pre>
<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>
<ul>
<li><code>2 &lt;= asteroids.length &lt;= 10<sup>4</sup></code></li>
<li><code>-1000 &lt;= asteroids[i] &lt;= 1000</code></li>
<li><code>asteroids[i] != 0</code></li>
</ul>
@@ -0,0 +1,32 @@
class Solution:
def deckRevealedIncreasing(self, deck: List[int]) -> List[int]:
"""
Complexities:
Time: O(n^2)
Space: O(n)
where n = len(deck)
"""
# run through a sample deck, save ordering
sample = [i for i in range(len(deck))]
revealedCards = []
while len(revealedCards) < len(deck):
revealedCards.append(sample[0])
sample.pop(0)
if len(sample) == 0:
break
sample.append(sample[0])
sample.pop(0)
# sort deck
deck.sort()
# replace sample with deck values
returnedArr = [-1] * len(deck)
for i in range(len(revealedCards)):
returnedArr[revealedCards[i]] = deck[i]
return returnedArr
@@ -0,0 +1,50 @@
<h2><a href="https://leetcode.com/problems/reveal-cards-in-increasing-order">950. Reveal Cards In Increasing Order</a></h2><h3>Medium</h3><hr><p>You are given an integer array <code>deck</code>. There is a deck of cards where every card has a unique integer. The integer on the <code>i<sup>th</sup></code> card is <code>deck[i]</code>.</p>
<p>You can order the deck in any order you want. Initially, all the cards start face down (unrevealed) in one deck.</p>
<p>You will do the following steps repeatedly until all cards are revealed:</p>
<ol>
<li>Take the top card of the deck, reveal it, and take it out of the deck.</li>
<li>If there are still cards in the deck then put the next top card of the deck at the bottom of the deck.</li>
<li>If there are still unrevealed cards, go back to step 1. Otherwise, stop.</li>
</ol>
<p>Return <em>an ordering of the deck that would reveal the cards in increasing order</em>.</p>
<p><strong>Note</strong> that the first entry in the answer is considered to be the top of the deck.</p>
<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<pre>
<strong>Input:</strong> deck = [17,13,11,2,3,5,7]
<strong>Output:</strong> [2,13,3,11,5,17,7]
<strong>Explanation:</strong>
We get the deck in the order [17,13,11,2,3,5,7] (this order does not matter), and reorder it.
After reordering, the deck starts as [2,13,3,11,5,17,7], where 2 is the top of the deck.
We reveal 2, and move 13 to the bottom. The deck is now [3,11,5,17,7,13].
We reveal 3, and move 11 to the bottom. The deck is now [5,17,7,13,11].
We reveal 5, and move 17 to the bottom. The deck is now [7,13,11,17].
We reveal 7, and move 13 to the bottom. The deck is now [11,17,13].
We reveal 11, and move 17 to the bottom. The deck is now [13,17].
We reveal 13, and move 17 to the bottom. The deck is now [17].
We reveal 17.
Since all the cards revealed are in increasing order, the answer is correct.
</pre>
<p><strong class="example">Example 2:</strong></p>
<pre>
<strong>Input:</strong> deck = [1,1000]
<strong>Output:</strong> [1,1000]
</pre>
<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>
<ul>
<li><code>1 &lt;= deck.length &lt;= 1000</code></li>
<li><code>1 &lt;= deck[i] &lt;= 10<sup>6</sup></code></li>
<li>All the values of <code>deck</code> are <strong>unique</strong>.</li>
</ul>
@@ -0,0 +1,44 @@
class Solution:
def makeGood(self, s: str) -> str:
"""
Complexities:
Time: O(n)
Space: O(n)
where n = len(s)
"""
# base case: len(s) == 1
if len(s) <= 1:
return s
stack = ""
for letter in s:
stack += letter
if len(stack) >= 2 and stack[-2] != stack[-1] and stack[-2].lower() == stack[-1].lower():
stack = stack[:-2]
return stack
"""
# iterate over all letters
# - compare s[i], s[i+1]
# - if I remove, look at s[i-1]
i = 0
while i <= len(s) - 2:
if s[i] != s[i + 1] and s[i].lower() == s[i + 1].lower():
s = s[:i] + s[i+2:]
if i > 0:
i -= 1
else:
i += 1
return s
"""
+48
View File
@@ -0,0 +1,48 @@
<h2><a href="https://leetcode.com/problems/make-the-string-great">1544. Make The String Great</a></h2><h3>Easy</h3><hr><p>Given a string <code>s</code> of lower and upper case English letters.</p>
<p>A good string is a string which doesn&#39;t have <strong>two adjacent characters</strong> <code>s[i]</code> and <code>s[i + 1]</code> where:</p>
<ul>
<li><code>0 &lt;= i &lt;= s.length - 2</code></li>
<li><code>s[i]</code> is a lower-case letter and <code>s[i + 1]</code> is the same letter but in upper-case or <strong>vice-versa</strong>.</li>
</ul>
<p>To make the string good, you can choose <strong>two adjacent</strong> characters that make the string bad and remove them. You can keep doing this until the string becomes good.</p>
<p>Return <em>the string</em> after making it good. The answer is guaranteed to be unique under the given constraints.</p>
<p><strong>Notice</strong> that an empty string is also good.</p>
<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<pre>
<strong>Input:</strong> s = &quot;leEeetcode&quot;
<strong>Output:</strong> &quot;leetcode&quot;
<strong>Explanation:</strong> In the first step, either you choose i = 1 or i = 2, both will result &quot;leEeetcode&quot; to be reduced to &quot;leetcode&quot;.
</pre>
<p><strong class="example">Example 2:</strong></p>
<pre>
<strong>Input:</strong> s = &quot;abBAcC&quot;
<strong>Output:</strong> &quot;&quot;
<strong>Explanation:</strong> We have many possible scenarios, and all lead to the same answer. For example:
&quot;abBAcC&quot; --&gt; &quot;aAcC&quot; --&gt; &quot;cC&quot; --&gt; &quot;&quot;
&quot;abBAcC&quot; --&gt; &quot;abBA&quot; --&gt; &quot;aA&quot; --&gt; &quot;&quot;
</pre>
<p><strong class="example">Example 3:</strong></p>
<pre>
<strong>Input:</strong> s = &quot;s&quot;
<strong>Output:</strong> &quot;s&quot;
</pre>
<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>
<ul>
<li><code>1 &lt;= s.length &lt;= 100</code></li>
<li><code>s</code> contains only lower and upper case English letters.</li>
</ul>
@@ -0,0 +1,56 @@
class Solution:
def minimumTime(self, n: int, relations: List[List[int]], time: List[int]) -> int:
"""
Complexities:
Time: O(n^2)
Space: O(r)
where n = n, r = len(relations)
"""
# courses been taken array
# - O(r) time / O(r) space
hasPrereq = [False] * n
prereqMap = [set() for i in range(n)]
leadsToMap = [set() for i in range(n)]
for prevCourse, nextCourse in relations:
hasPrereq[nextCourse - 1] = True
prereqMap[nextCourse - 1].add(prevCourse)
leadsToMap[prevCourse - 1].add(nextCourse)
# O(n) space
timeUntilComplete = [-1] * n
coursesCalculated = 0
maxOverallTimeFound = 0
toResolve = set()
# calculate timeUntilComplete for no prereq courses
# - O(n) time
for i in range(n):
if not hasPrereq[i]:
timeUntilComplete[i] = time[i]
maxOverallTimeFound = max(maxOverallTimeFound, time[i])
coursesCalculated += 1
toResolve.update(leadsToMap[i])
# find all timeUntilComplete
# - if all prereq times are known, then calc
# - O(n^2) time
while len(toResolve) > 0:
nextCourse = toResolve.pop()
maxPrereqTime = -1
for prereq in prereqMap[nextCourse - 1]:
if timeUntilComplete[prereq - 1] == -1:
maxPrereqTime = -1
break
maxPrereqTime = max(maxPrereqTime, timeUntilComplete[prereq - 1])
if maxPrereqTime > -1:
timeUntilComplete[nextCourse - 1] = maxPrereqTime + time[nextCourse - 1]
maxOverallTimeFound = max(maxOverallTimeFound, timeUntilComplete[nextCourse - 1])
coursesCalculated += 1
toResolve.update(leadsToMap[nextCourse - 1])
return maxOverallTimeFound
+54
View File
@@ -0,0 +1,54 @@
<h2><a href="https://leetcode.com/problems/parallel-courses-iii">2050. Parallel Courses III</a></h2><h3>Hard</h3><hr><p>You are given an integer <code>n</code>, which indicates that there are <code>n</code> courses labeled from <code>1</code> to <code>n</code>. You are also given a 2D integer array <code>relations</code> where <code>relations[j] = [prevCourse<sub>j</sub>, nextCourse<sub>j</sub>]</code> denotes that course <code>prevCourse<sub>j</sub></code> has to be completed <strong>before</strong> course <code>nextCourse<sub>j</sub></code> (prerequisite relationship). Furthermore, you are given a <strong>0-indexed</strong> integer array <code>time</code> where <code>time[i]</code> denotes how many <strong>months</strong> it takes to complete the <code>(i+1)<sup>th</sup></code> course.</p>
<p>You must find the <strong>minimum</strong> number of months needed to complete all the courses following these rules:</p>
<ul>
<li>You may start taking a course at <strong>any time</strong> if the prerequisites are met.</li>
<li><strong>Any number of courses</strong> can be taken at the <strong>same time</strong>.</li>
</ul>
<p>Return <em>the <strong>minimum</strong> number of months needed to complete all the courses</em>.</p>
<p><strong>Note:</strong> The test cases are generated such that it is possible to complete every course (i.e., the graph is a directed acyclic graph).</p>
<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<strong><img alt="" src="https://assets.leetcode.com/uploads/2021/10/07/ex1.png" style="width: 392px; height: 232px;" /></strong>
<pre>
<strong>Input:</strong> n = 3, relations = [[1,3],[2,3]], time = [3,2,5]
<strong>Output:</strong> 8
<strong>Explanation:</strong> The figure above represents the given graph and the time required to complete each course.
We start course 1 and course 2 simultaneously at month 0.
Course 1 takes 3 months and course 2 takes 2 months to complete respectively.
Thus, the earliest time we can start course 3 is at month 3, and the total time required is 3 + 5 = 8 months.
</pre>
<p><strong class="example">Example 2:</strong></p>
<strong><img alt="" src="https://assets.leetcode.com/uploads/2021/10/07/ex2.png" style="width: 500px; height: 365px;" /></strong>
<pre>
<strong>Input:</strong> n = 5, relations = [[1,5],[2,5],[3,5],[3,4],[4,5]], time = [1,2,3,4,5]
<strong>Output:</strong> 12
<strong>Explanation:</strong> The figure above represents the given graph and the time required to complete each course.
You can start courses 1, 2, and 3 at month 0.
You can complete them after 1, 2, and 3 months respectively.
Course 4 can be taken only after course 3 is completed, i.e., after 3 months. It is completed after 3 + 4 = 7 months.
Course 5 can be taken only after courses 1, 2, 3, and 4 have been completed, i.e., after max(1,2,3,7) = 7 months.
Thus, the minimum time needed to complete all the courses is 7 + 5 = 12 months.
</pre>
<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>
<ul>
<li><code>1 &lt;= n &lt;= 5 * 10<sup>4</sup></code></li>
<li><code>0 &lt;= relations.length &lt;= min(n * (n - 1) / 2, 5 * 10<sup>4</sup>)</code></li>
<li><code>relations[j].length == 2</code></li>
<li><code>1 &lt;= prevCourse<sub>j</sub>, nextCourse<sub>j</sub> &lt;= n</code></li>
<li><code>prevCourse<sub>j</sub> != nextCourse<sub>j</sub></code></li>
<li>All the pairs <code>[prevCourse<sub>j</sub>, nextCourse<sub>j</sub>]</code> are <strong>unique</strong>.</li>
<li><code>time.length == n</code></li>
<li><code>1 &lt;= time[i] &lt;= 10<sup>4</sup></code></li>
<li>The given graph is a directed acyclic graph.</li>
</ul>
@@ -0,0 +1,17 @@
class Solution:
def bestClosingTime(self, customers: str) -> int:
penalty = 0
minPenalty = 0
bestHour = 0
for hour, hasCustomers in enumerate(customers):
if hasCustomers == "Y":
penalty -= 1
else:
penalty += 1
if penalty < minPenalty:
minPenalty = penalty
bestHour = hour + 1
return bestHour
+55
View File
@@ -0,0 +1,55 @@
<h2><a href="https://leetcode.com/problems/minimum-penalty-for-a-shop">2483. Minimum Penalty for a Shop</a></h2><h3>Medium</h3><hr><p>You are given the customer visit log of a shop represented by a <strong>0-indexed</strong> string <code>customers</code> consisting only of characters <code>&#39;N&#39;</code> and <code>&#39;Y&#39;</code>:</p>
<ul>
<li>if the <code>i<sup>th</sup></code> character is <code>&#39;Y&#39;</code>, it means that customers come at the <code>i<sup>th</sup></code> hour</li>
<li>whereas <code>&#39;N&#39;</code> indicates that no customers come at the <code>i<sup>th</sup></code> hour.</li>
</ul>
<p>If the shop closes at the <code>j<sup>th</sup></code> hour (<code>0 &lt;= j &lt;= n</code>), the <strong>penalty</strong> is calculated as follows:</p>
<ul>
<li>For every hour when the shop is open and no customers come, the penalty increases by <code>1</code>.</li>
<li>For every hour when the shop is closed and customers come, the penalty increases by <code>1</code>.</li>
</ul>
<p>Return<em> the <strong>earliest</strong> hour at which the shop must be closed to incur a <strong>minimum</strong> penalty.</em></p>
<p><strong>Note</strong> that if a shop closes at the <code>j<sup>th</sup></code> hour, it means the shop is closed at the hour <code>j</code>.</p>
<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<pre>
<strong>Input:</strong> customers = &quot;YYNY&quot;
<strong>Output:</strong> 2
<strong>Explanation:</strong>
- Closing the shop at the 0<sup>th</sup> hour incurs in 1+1+0+1 = 3 penalty.
- Closing the shop at the 1<sup>st</sup> hour incurs in 0+1+0+1 = 2 penalty.
- Closing the shop at the 2<sup>nd</sup> hour incurs in 0+0+0+1 = 1 penalty.
- Closing the shop at the 3<sup>rd</sup> hour incurs in 0+0+1+1 = 2 penalty.
- Closing the shop at the 4<sup>th</sup> hour incurs in 0+0+1+0 = 1 penalty.
Closing the shop at 2<sup>nd</sup> or 4<sup>th</sup> hour gives a minimum penalty. Since 2 is earlier, the optimal closing time is 2.
</pre>
<p><strong class="example">Example 2:</strong></p>
<pre>
<strong>Input:</strong> customers = &quot;NNNNN&quot;
<strong>Output:</strong> 0
<strong>Explanation:</strong> It is best to close the shop at the 0<sup>th</sup> hour as no customers arrive.</pre>
<p><strong class="example">Example 3:</strong></p>
<pre>
<strong>Input:</strong> customers = &quot;YYYY&quot;
<strong>Output:</strong> 4
<strong>Explanation:</strong> It is best to close the shop at the 4<sup>th</sup> hour as customers arrive at each hour.
</pre>
<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>
<ul>
<li><code>1 &lt;= customers.length &lt;= 10<sup>5</sup></code></li>
<li><code>customers</code> consists only of characters <code>&#39;Y&#39;</code> and <code>&#39;N&#39;</code>.</li>
</ul>