Category: LeetCode Solutions

  • LeetCode 2: Add Two Numbers — Python Solution

    Solve LeetCode 2: Add Two Numbers in Python with a digitwise carry approach. The key is to make the state invariant explicit, so the implementation and complexity follow naturally.

    This guide paraphrases the task and does not reproduce LeetCode’s prompt. Use the official page for the complete statement, examples, constraints, and submission runner.

    DifficultyMedium
    TopicLinked List
    Reusable patterndigitwise carry
    ComplexityO(max(m,n)) time and O(max(m,n)) output space

    What the problem is testing

    Walk both reverse-order digit lists, add available digits plus carry, and append the ones digit while carrying the tens digit.

    Algorithm

    1. Walk both reverse-order digit lists, add available digits plus carry, and append the ones digit while carrying the tens digit.
    2. Maintain this invariant: The output prefix represents the exact sum of the processed digit positions.
    3. Continue until every input item or reachable state has been resolved, then return the accumulated result.

    Python solution

    LeetCode provides the list, tree, or graph node definition used by the method.

    from collections import Counter, defaultdict, deque, OrderedDict
    import random
    
    class Solution:
        def addTwoNumbers(self, l1, l2):
            dummy = tail = ListNode()
            carry = 0
            while l1 or l2 or carry:
                total = carry
                if l1: total += l1.val; l1 = l1.next
                if l2: total += l2.val; l2 = l2.next
                carry, digit = divmod(total, 10)
                tail.next = ListNode(digit)
                tail = tail.next
            return dummy.next

    Why this is correct

    The proof follows the maintained state: The output prefix represents the exact sum of the processed digit positions. Each iteration preserves that claim while permanently resolving at least one position, node, interval, or search state. When the loop or recursion ends, every candidate required by the problem has therefore been included or ruled out, so the returned value is correct.

    Complexity

    O(max(m,n)) time and O(max(m,n)) output space. The stated auxiliary space excludes the returned output unless the output is the data structure being built.

    Edge cases

    A final carry creates a new node; lists can have different lengths.

    Tested reference code

    This implementation is included in the site’s downloadable 100-solution Python library. The complete suite compiles every solution and runs a behavioral assertion for every problem before publication.


    Browse the searchable 100 LeetCode Python Solutions hub. Previous: 141. Linked List Cycle · Next: 21. Merge Two Sorted Lists

  • LeetCode 21: Merge Two Sorted Lists — Python Solution

    Solve LeetCode 21: Merge Two Sorted Lists in Python with a dummy-tail merge approach. The key is to make the state invariant explicit, so the implementation and complexity follow naturally.

    This guide paraphrases the task and does not reproduce LeetCode’s prompt. Use the official page for the complete statement, examples, constraints, and submission runner.

    DifficultyEasy
    TopicLinked List
    Reusable patterndummy-tail merge
    ComplexityO(m+n) time and O(1) extra space

    What the problem is testing

    Attach the smaller current node to a dummy-backed output tail, advance that list, then attach the unexhausted suffix.

    Algorithm

    1. Attach the smaller current node to a dummy-backed output tail, advance that list, then attach the unexhausted suffix.
    2. Maintain this invariant: The output through tail is sorted and contains exactly the consumed input nodes.
    3. Continue until every input item or reachable state has been resolved, then return the accumulated result.

    Python solution

    LeetCode provides the list, tree, or graph node definition used by the method.

    from collections import Counter, defaultdict, deque, OrderedDict
    import random
    
    class Solution:
        def mergeTwoLists(self, list1, list2):
            dummy = tail = ListNode()
            while list1 and list2:
                if list1.val <= list2.val:
                    tail.next, list1 = list1, list1.next
                else:
                    tail.next, list2 = list2, list2.next
                tail = tail.next
            tail.next = list1 or list2
            return dummy.next

    Why this is correct

    The proof follows the maintained state: The output through tail is sorted and contains exactly the consumed input nodes. Each iteration preserves that claim while permanently resolving at least one position, node, interval, or search state. When the loop or recursion ends, every candidate required by the problem has therefore been included or ruled out, so the returned value is correct.

    Complexity

    O(m+n) time and O(1) extra space. The stated auxiliary space excludes the returned output unless the output is the data structure being built.

    Edge cases

    Either list may be empty; nodes can be reused rather than copied.

    Tested reference code

    This implementation is included in the site’s downloadable 100-solution Python library. The complete suite compiles every solution and runs a behavioral assertion for every problem before publication.


    Browse the searchable 100 LeetCode Python Solutions hub. Previous: 2. Add Two Numbers · Next: 138. Copy List with Random Pointer

  • LeetCode 138: Copy List with Random Pointer — Python Solution

    Solve LeetCode 138: Copy List with Random Pointer in Python with a node-to-copy map approach. The key is to make the state invariant explicit, so the implementation and complexity follow naturally.

    This guide paraphrases the task and does not reproduce LeetCode’s prompt. Use the official page for the complete statement, examples, constraints, and submission runner.

    DifficultyMedium
    TopicLinked List
    Reusable patternnode-to-copy map
    ComplexityO(n) time and O(n) space

    What the problem is testing

    Create one copy per original node, then wire next and random pointers by looking up their copied targets.

    Algorithm

    1. Create one copy per original node, then wire next and random pointers by looking up their copied targets.
    2. Maintain this invariant: The map contains the unique clone for every original node before any cloned edge is assigned.
    3. Continue until every input item or reachable state has been resolved, then return the accumulated result.

    Python solution

    LeetCode provides the list, tree, or graph node definition used by the method.

    from collections import Counter, defaultdict, deque, OrderedDict
    import random
    
    class Solution:
        def copyRandomList(self, head):
            if not head:
                return None
            copies = {}
            current = head
            while current:
                copies[current] = Node(current.val)
                current = current.next
            current = head
            while current:
                copies[current].next = copies.get(current.next)
                copies[current].random = copies.get(current.random)
                current = current.next
            return copies[head]

    Why this is correct

    The proof follows the maintained state: The map contains the unique clone for every original node before any cloned edge is assigned. Each iteration preserves that claim while permanently resolving at least one position, node, interval, or search state. When the loop or recursion ends, every candidate required by the problem has therefore been included or ruled out, so the returned value is correct.

    Complexity

    O(n) time and O(n) space. The stated auxiliary space excludes the returned output unless the output is the data structure being built.

    Edge cases

    Random pointers may be null, self-referential, or point backward.

    Tested reference code

    This implementation is included in the site’s downloadable 100-solution Python library. The complete suite compiles every solution and runs a behavioral assertion for every problem before publication.


    Browse the searchable 100 LeetCode Python Solutions hub. Previous: 21. Merge Two Sorted Lists · Next: 92. Reverse Linked List II

  • LeetCode 92: Reverse Linked List II — Python Solution

    Solve LeetCode 92: Reverse Linked List II in Python with a head insertion reversal approach. The key is to make the state invariant explicit, so the implementation and complexity follow naturally.

    This guide paraphrases the task and does not reproduce LeetCode’s prompt. Use the official page for the complete statement, examples, constraints, and submission runner.

    DifficultyMedium
    TopicLinked List
    Reusable patternhead insertion reversal
    ComplexityO(n) time and O(1) extra space

    What the problem is testing

    Reach the node before the target segment, then repeatedly remove the next segment node and insert it at the segment front.

    Algorithm

    1. Reach the node before the target segment, then repeatedly remove the next segment node and insert it at the segment front.
    2. Maintain this invariant: After each insertion, the processed portion of the target segment is reversed in place.
    3. Continue until every input item or reachable state has been resolved, then return the accumulated result.

    Python solution

    LeetCode provides the list, tree, or graph node definition used by the method.

    from collections import Counter, defaultdict, deque, OrderedDict
    import random
    
    class Solution:
        def reverseBetween(self, head, left, right):
            dummy = ListNode(0, head)
            before = dummy
            for _ in range(left - 1):
                before = before.next
            tail = before.next
            for _ in range(right - left):
                moved = tail.next
                tail.next = moved.next
                moved.next = before.next
                before.next = moved
            return dummy.next

    Why this is correct

    The proof follows the maintained state: After each insertion, the processed portion of the target segment is reversed in place. Each iteration preserves that claim while permanently resolving at least one position, node, interval, or search state. When the loop or recursion ends, every candidate required by the problem has therefore been included or ruled out, so the returned value is correct.

    Complexity

    O(n) time and O(1) extra space. The stated auxiliary space excludes the returned output unless the output is the data structure being built.

    Edge cases

    Reversing from the head is handled by the dummy node; left may equal right.

    Tested reference code

    This implementation is included in the site’s downloadable 100-solution Python library. The complete suite compiles every solution and runs a behavioral assertion for every problem before publication.


    Browse the searchable 100 LeetCode Python Solutions hub. Previous: 138. Copy List with Random Pointer · Next: 25. Reverse Nodes in k-Group

  • LeetCode 452: Minimum Number of Arrows to Burst Balloons — Python Solution

    Solve LeetCode 452: Minimum Number of Arrows to Burst Balloons in Python with a greedy earliest end approach. The key is to make the state invariant explicit, so the implementation and complexity follow naturally.

    This guide paraphrases the task and does not reproduce LeetCode’s prompt. Use the official page for the complete statement, examples, constraints, and submission runner.

    DifficultyMedium
    TopicIntervals
    Reusable patterngreedy earliest end
    ComplexityO(n log n) time and O(1) auxiliary space aside from sorting

    What the problem is testing

    Sort balloons by ending coordinate and shoot at the earliest possible end; add an arrow only when the next interval starts after that point.

    Algorithm

    1. Sort balloons by ending coordinate and shoot at the earliest possible end; add an arrow only when the next interval starts after that point.
    2. Maintain this invariant: The current arrow bursts every interval processed since the last arrow and leaves maximum room for future overlaps.
    3. Continue until every input item or reachable state has been resolved, then return the accumulated result.

    Python solution

    from collections import Counter, defaultdict, deque, OrderedDict
    import random
    
    class Solution:
        def findMinArrowShots(self, points):
            if not points:
                return 0
            points.sort(key=lambda interval: interval[1])
            arrows, position = 1, points[0][1]
            for start, end in points[1:]:
                if start > position:
                    arrows += 1
                    position = end
            return arrows

    Why this is correct

    The proof follows the maintained state: The current arrow bursts every interval processed since the last arrow and leaves maximum room for future overlaps. Each iteration preserves that claim while permanently resolving at least one position, node, interval, or search state. When the loop or recursion ends, every candidate required by the problem has therefore been included or ruled out, so the returned value is correct.

    Complexity

    O(n log n) time and O(1) auxiliary space aside from sorting. The stated auxiliary space excludes the returned output unless the output is the data structure being built.

    Edge cases

    Intervals touching the arrow coordinate are burst by the same arrow.

    Tested reference code

    This implementation is included in the site’s downloadable 100-solution Python library. The complete suite compiles every solution and runs a behavioral assertion for every problem before publication.


    Browse the searchable 100 LeetCode Python Solutions hub. Previous: 57. Insert Interval · Next: 20. Valid Parentheses

  • LeetCode 20: Valid Parentheses — Python Solution

    Solve LeetCode 20: Valid Parentheses in Python with a expected-closer stack approach. The key is to make the state invariant explicit, so the implementation and complexity follow naturally.

    This guide paraphrases the task and does not reproduce LeetCode’s prompt. Use the official page for the complete statement, examples, constraints, and submission runner.

    DifficultyEasy
    TopicStack
    Reusable patternexpected-closer stack
    ComplexityO(n) time and O(n) space

    What the problem is testing

    Push the required closing symbol for every opener; each closer must match the most recently expected symbol.

    Algorithm

    1. Push the required closing symbol for every opener; each closer must match the most recently expected symbol.
    2. Maintain this invariant: The stack contains exactly the closing symbols needed for unmatched openers.
    3. Continue until every input item or reachable state has been resolved, then return the accumulated result.

    Python solution

    from collections import Counter, defaultdict, deque, OrderedDict
    import random
    
    class Solution:
        def isValid(self, s):
            expected = []
            pairs = {"(": ")", "[": "]", "{": "}"}
            for char in s:
                if char in pairs:
                    expected.append(pairs[char])
                elif not expected or expected.pop() != char:
                    return False
            return not expected

    Why this is correct

    The proof follows the maintained state: The stack contains exactly the closing symbols needed for unmatched openers. Each iteration preserves that claim while permanently resolving at least one position, node, interval, or search state. When the loop or recursion ends, every candidate required by the problem has therefore been included or ruled out, so the returned value is correct.

    Complexity

    O(n) time and O(n) space. The stated auxiliary space excludes the returned output unless the output is the data structure being built.

    Edge cases

    A closer on an empty stack or leftover openers makes the string invalid.

    Tested reference code

    This implementation is included in the site’s downloadable 100-solution Python library. The complete suite compiles every solution and runs a behavioral assertion for every problem before publication.


    Browse the searchable 100 LeetCode Python Solutions hub. Previous: 452. Minimum Number of Arrows to Burst Balloons · Next: 71. Simplify Path

  • LeetCode 71: Simplify Path — Python Solution

    Solve LeetCode 71: Simplify Path in Python with a canonical path stack approach. The key is to make the state invariant explicit, so the implementation and complexity follow naturally.

    This guide paraphrases the task and does not reproduce LeetCode’s prompt. Use the official page for the complete statement, examples, constraints, and submission runner.

    DifficultyMedium
    TopicStack
    Reusable patterncanonical path stack
    ComplexityO(n) time and O(n) space

    What the problem is testing

    Ignore empty and dot components, pop on double-dot when possible, and push ordinary directory names.

    Algorithm

    1. Ignore empty and dot components, pop on double-dot when possible, and push ordinary directory names.
    2. Maintain this invariant: The stack is the canonical absolute path for all processed components.
    3. Continue until every input item or reachable state has been resolved, then return the accumulated result.

    Python solution

    from collections import Counter, defaultdict, deque, OrderedDict
    import random
    
    class Solution:
        def simplifyPath(self, path):
            stack = []
            for part in path.split("/"):
                if part in ("", "."):
                    continue
                if part == "..":
                    if stack: stack.pop()
                else:
                    stack.append(part)
            return "/" + "/".join(stack)

    Why this is correct

    The proof follows the maintained state: The stack is the canonical absolute path for all processed components. Each iteration preserves that claim while permanently resolving at least one position, node, interval, or search state. When the loop or recursion ends, every candidate required by the problem has therefore been included or ruled out, so the returned value is correct.

    Complexity

    O(n) time and O(n) space. The stated auxiliary space excludes the returned output unless the output is the data structure being built.

    Edge cases

    Attempts to move above root have no effect; repeated slashes are ignored.

    Tested reference code

    This implementation is included in the site’s downloadable 100-solution Python library. The complete suite compiles every solution and runs a behavioral assertion for every problem before publication.


    Browse the searchable 100 LeetCode Python Solutions hub. Previous: 20. Valid Parentheses · Next: 155. Min Stack

  • LeetCode 155: Min Stack — Python Solution

    Solve LeetCode 155: Min Stack in Python with a paired minimum stack approach. The key is to make the state invariant explicit, so the implementation and complexity follow naturally.

    This guide paraphrases the task and does not reproduce LeetCode’s prompt. Use the official page for the complete statement, examples, constraints, and submission runner.

    DifficultyMedium
    TopicStack
    Reusable patternpaired minimum stack
    ComplexityO(1) time per operation and O(n) space

    What the problem is testing

    Store each pushed value together with the minimum at that stack depth so minimum queries never scan.

    Algorithm

    1. Store each pushed value together with the minimum at that stack depth so minimum queries never scan.
    2. Maintain this invariant: The stored minimum in each entry equals the minimum of the stack prefix ending there.
    3. Continue until every input item or reachable state has been resolved, then return the accumulated result.

    Python solution

    from collections import Counter, defaultdict, deque, OrderedDict
    import random
    
    class MinStack:
        def __init__(self):
            self.stack = []
    
        def push(self, val):
            minimum = val if not self.stack else min(val, self.stack[-1][1])
            self.stack.append((val, minimum))
    
        def pop(self):
            self.stack.pop()
    
        def top(self):
            return self.stack[-1][0]
    
        def getMin(self):
            return self.stack[-1][1]

    Why this is correct

    The proof follows the maintained state: The stored minimum in each entry equals the minimum of the stack prefix ending there. Each iteration preserves that claim while permanently resolving at least one position, node, interval, or search state. When the loop or recursion ends, every candidate required by the problem has therefore been included or ruled out, so the returned value is correct.

    Complexity

    O(1) time per operation and O(n) space. The stated auxiliary space excludes the returned output unless the output is the data structure being built.

    Edge cases

    Duplicate minima must be preserved until every matching entry is popped.

    Tested reference code

    This implementation is included in the site’s downloadable 100-solution Python library. The complete suite compiles every solution and runs a behavioral assertion for every problem before publication.


    Browse the searchable 100 LeetCode Python Solutions hub. Previous: 71. Simplify Path · Next: 150. Evaluate Reverse Polish Notation

  • LeetCode 150: Evaluate Reverse Polish Notation — Python Solution

    Solve LeetCode 150: Evaluate Reverse Polish Notation in Python with a operand stack approach. The key is to make the state invariant explicit, so the implementation and complexity follow naturally.

    This guide paraphrases the task and does not reproduce LeetCode’s prompt. Use the official page for the complete statement, examples, constraints, and submission runner.

    DifficultyMedium
    TopicStack
    Reusable patternoperand stack
    ComplexityO(n) time and O(n) space

    What the problem is testing

    Push numbers and, for each operator, pop the right operand then the left operand, apply the operation, and push the result.

    Algorithm

    1. Push numbers and, for each operator, pop the right operand then the left operand, apply the operation, and push the result.
    2. Maintain this invariant: The stack contains the evaluated values of complete subexpressions in the processed token prefix.
    3. Continue until every input item or reachable state has been resolved, then return the accumulated result.

    Python solution

    from collections import Counter, defaultdict, deque, OrderedDict
    import random
    
    class Solution:
        def evalRPN(self, tokens):
            stack = []
            for token in tokens:
                if token not in {"+", "-", "*", "/"}:
                    stack.append(int(token))
                    continue
                right, left = stack.pop(), stack.pop()
                if token == "+": stack.append(left + right)
                elif token == "-": stack.append(left - right)
                elif token == "*": stack.append(left * right)
                else: stack.append(int(left / right))
            return stack[-1]

    Why this is correct

    The proof follows the maintained state: The stack contains the evaluated values of complete subexpressions in the processed token prefix. Each iteration preserves that claim while permanently resolving at least one position, node, interval, or search state. When the loop or recursion ends, every candidate required by the problem has therefore been included or ruled out, so the returned value is correct.

    Complexity

    O(n) time and O(n) space. The stated auxiliary space excludes the returned output unless the output is the data structure being built.

    Edge cases

    Division truncates toward zero and operand order matters for subtraction and division.

    Tested reference code

    This implementation is included in the site’s downloadable 100-solution Python library. The complete suite compiles every solution and runs a behavioral assertion for every problem before publication.


    Browse the searchable 100 LeetCode Python Solutions hub. Previous: 155. Min Stack · Next: 224. Basic Calculator

  • LeetCode 224: Basic Calculator — Python Solution

    Solve LeetCode 224: Basic Calculator in Python with a sign-context stack approach. The key is to make the state invariant explicit, so the implementation and complexity follow naturally.

    This guide paraphrases the task and does not reproduce LeetCode’s prompt. Use the official page for the complete statement, examples, constraints, and submission runner.

    DifficultyHard
    TopicStack
    Reusable patternsign-context stack
    ComplexityO(n) time and O(n) space

    What the problem is testing

    Accumulate a number with the current sign. On an opening parenthesis, save the outer result and sign; on closing, combine the completed inner result.

    Algorithm

    1. Accumulate a number with the current sign. On an opening parenthesis, save the outer result and sign; on closing, combine the completed inner result.
    2. Maintain this invariant: result is the value of completed terms in the current parenthesis level, with sign describing the next number or group.
    3. Continue until every input item or reachable state has been resolved, then return the accumulated result.

    Python solution

    from collections import Counter, defaultdict, deque, OrderedDict
    import random
    
    class Solution:
        def calculate(self, s):
            result, number, sign = 0, 0, 1
            stack = []
            for char in s + "+":
                if char.isdigit():
                    number = number * 10 + int(char)
                elif char in "+-":
                    result += sign * number
                    number = 0
                    sign = 1 if char == "+" else -1
                elif char == "(":
                    stack.append(result)
                    stack.append(sign)
                    result, sign = 0, 1
                elif char == ")":
                    result += sign * number
                    number = 0
                    result = stack.pop() * result + stack.pop()
            return result

    Why this is correct

    The proof follows the maintained state: result is the value of completed terms in the current parenthesis level, with sign describing the next number or group. Each iteration preserves that claim while permanently resolving at least one position, node, interval, or search state. When the loop or recursion ends, every candidate required by the problem has therefore been included or ruled out, so the returned value is correct.

    Complexity

    O(n) time and O(n) space. The stated auxiliary space excludes the returned output unless the output is the data structure being built.

    Edge cases

    Spaces are ignored; unary minus and nested parentheses use the same sign mechanism.

    Tested reference code

    This implementation is included in the site’s downloadable 100-solution Python library. The complete suite compiles every solution and runs a behavioral assertion for every problem before publication.


    Browse the searchable 100 LeetCode Python Solutions hub. Previous: 150. Evaluate Reverse Polish Notation · Next: 141. Linked List Cycle