2300. Successful Pairs of Spells and Potions - Explanation

Problem Link



1. Brute Force

class Solution:
    def successfulPairs(self, spells: List[int], potions: List[int], success: int) -> List[int]:
        res = []

        for s in spells:
            cnt = 0
            for p in potions:
                if s * p >= success:
                    cnt += 1
            res.append(cnt)

        return res

Time & Space Complexity

  • Time complexity: O(nm)O(n * m)
  • Space complexity: O(1)O(1)

Where nn and mm are the sizes of the arrays spellsspells and potionspotions respectively.


class Solution:
    def successfulPairs(self, spells: List[int], potions: List[int], success: int) -> List[int]:
        potions.sort()
        res = []

        for s in spells:
            l, r = 0, len(potions) - 1
            idx = len(potions)

            while l <= r:
                m = (l + r) // 2
                if s * potions[m] >= success:
                    r = m - 1
                    idx = m
                else:
                    l = m + 1

            res.append(len(potions) - idx)

        return res

Time & Space Complexity

  • Time complexity: O((m+n)logm)O((m + n) * \log m)
  • Space complexity:
    • O(1)O(1) or O(m)O(m) extra space depending on the sorting algorithm.
    • O(n)O(n) space for the output array.

Where nn and mm are the sizes of the arrays spellsspells and potionspotions respectively.


3. Sorting + Two Pointers

class Solution:
    def successfulPairs(self, spells: List[int], potions: List[int], success: int) -> List[int]:
        n, m = len(spells), len(potions)
        S = spells[:]
        count = defaultdict(int)
        spells.sort()
        potions.sort()

        j = m - 1
        for i in range(n):
            while j >= 0 and spells[i] * potions[j] >= success:
                j -= 1
            count[spells[i]] = m - j - 1

        res = [0] * n
        for i in range(n):
            res[i] = count[S[i]]

        return res

Time & Space Complexity

  • Time complexity: O(nlogn+mlogm)O(n \log n + m\log m)
  • Space complexity:
    • O(1)O(1) or O(m+n)O(m + n) extra space depending on the sorting algorithm.
    • O(n)O(n) space for the output array.

Where nn and mm are the sizes of the arrays spellsspells and potionspotions respectively.


4. Sorting + Two Pointers (Optimal)

class Solution:
    def successfulPairs(self, spells: List[int], potions: List[int], success: int) -> List[int]:
        n, m = len(spells), len(potions)
        sIdx = list(range(n))
        sIdx.sort(key=lambda x: spells[x])
        potions.sort()

        j = m - 1
        res = [0] * n
        for i in range(n):
            while j >= 0 and spells[sIdx[i]] * potions[j] >= success:
                j -= 1
            res[sIdx[i]] = m - j - 1

        return res

Time & Space Complexity

  • Time complexity: O(nlogn+mlogm)O(n \log n + m\log m)
  • Space complexity:
    • O(1)O(1) or O(m+n)O(m + n) extra space depending on the sorting algorithm.
    • O(n)O(n) space for the output array.

Where nn and mm are the sizes of the arrays spellsspells and potionspotions respectively.