|
| 1 | +# [Successful Pairs of Spells and Potions](https://leetcode.com/problems/successful-pairs-of-spells-and-potions/) |
| 2 | + |
| 3 | +## Question Description |
| 4 | +You are given two positive integer arrays `spells` and `potions`, of lengths `n` and `m` respectively, where `spells[i]` represents the strength of the `ith` spell and `potions[j]` represents the strength of the `jth` potion. |
| 5 | + |
| 6 | +You are also given an integer `success`. A spell and potion pair is considered **successful** if the product of their strengths is **at least** `success`. |
| 7 | + |
| 8 | +Return an integer array `pairs` of length `n`, where `pairs[i]` is the number of potions that will form a successful pair with the `ith` spell. |
| 9 | + |
| 10 | +--- |
| 11 | + |
| 12 | +## Constraints |
| 13 | +- `n == spells.length` |
| 14 | +- `m == potions.length` |
| 15 | +- `1 <= n, m <= 10^5` |
| 16 | +- `1 <= spells[i], potions[i] <= 10^4` |
| 17 | +- `1 <= success <= 10^14` |
| 18 | + |
| 19 | +--- |
| 20 | + |
| 21 | +## Approaches |
| 22 | + |
| 23 | +### Approach 1: Brute Force |
| 24 | +Check every possible spell-potion pair and count how many satisfy the success condition. |
| 25 | + |
| 26 | +**Algorithm:** |
| 27 | +1. For each spell in the spells array |
| 28 | +2. For each potion in the potions array |
| 29 | +3. Check if `spell[i] * potion[j] >= success` |
| 30 | +4. If true, increment the count for that spell |
| 31 | +5. Store the count in the result array |
| 32 | + |
| 33 | +--- |
| 34 | + |
| 35 | +## Dry Run (Brute Force) |
| 36 | +Example Input: `spells = [5,1,3], potions = [1,2,3,4,5], success = 7` |
| 37 | + |
| 38 | +Step-by-step execution: |
| 39 | +- For spell=5 (i=0): |
| 40 | + - 5 * 1 = 5 < 7 → skip |
| 41 | + - 5 * 2 = 10 < 7 → skip |
| 42 | + - 5 * 3 = 15 >= 7 → count = 1 |
| 43 | + - 5 * 4 = 20 >= 7 → count = 2 |
| 44 | + - 5 * 5 = 25 >= 7 → count = 3 |
| 45 | + - Result: arr[0] = 3 ✓ |
| 46 | +- For spell=1 (i=1): |
| 47 | + - 1 * 1 = 1 < 7 → skip |
| 48 | + - 1 * 2 = 2 < 7 → skip |
| 49 | + - 1 * 3 = 3 < 7 → skip |
| 50 | + - 1 * 4 = 4 < 7 → skip |
| 51 | + - 1 * 5 = 5 < 7 → skip |
| 52 | + - Result: arr[1] = 0 ✓ |
| 53 | +- For spell=3 (i=2): |
| 54 | + - 3 * 1 = 3 < 7 → skip |
| 55 | + - 3 * 2 = 6 < 7 → skip |
| 56 | + - 3 * 3 = 9 >= 7 → count = 1 |
| 57 | + - 3 * 4 = 12 >= 7 → count = 2 |
| 58 | + - 3 * 5 = 15 >= 7 → count = 3 |
| 59 | + - Result: arr[2] = 3 ✓ |
| 60 | + |
| 61 | +Final Answer = `[3,0,3]` |
| 62 | + |
| 63 | +--- |
| 64 | + |
| 65 | +## Solution (Brute Force) |
| 66 | +```java |
| 67 | +class Solution { |
| 68 | + public int[] successfulPairs(int[] spells, int[] potions, long success) { |
| 69 | + int arr[] = new int[spells.length]; |
| 70 | + for (int i = 0; i < spells.length; i++) { |
| 71 | + int count = 0; |
| 72 | + for (int j = 0; j < potions.length; j++) { |
| 73 | + if (spells[i] * potions[j] >= success) { |
| 74 | + count++; |
| 75 | + } |
| 76 | + } |
| 77 | + arr[i] = count; |
| 78 | + } |
| 79 | + return arr; |
| 80 | + } |
| 81 | +} |
| 82 | +``` |
| 83 | + |
| 84 | +--- |
| 85 | + |
| 86 | +## Time and Space Complexity (Brute Force) |
| 87 | +- **Time Complexity:** O(n * m) - nested loops iterate through all spell-potion pairs |
| 88 | +- **Space Complexity:** O(1) - excluding the output array, only using constant extra space |
| 89 | + |
| 90 | +--- |
| 91 | + |
| 92 | +### Approach 2: Binary Search (Optimal) |
| 93 | +Sort the potions array first. For each spell, use binary search to find the smallest index where `potions[mid] * spell >= success`. This gives us the first potion that can form a successful pair with the current spell. The number of successful potions is then `m - firstSuccessfulPotionIndex`. |
| 94 | + |
| 95 | +**Algorithm:** |
| 96 | +1. Sort the potions array |
| 97 | +2. For each spell, use binary search to find the minimum index where the condition is satisfied |
| 98 | +3. The count is `m - firstSuccessfulPotionIndex` |
| 99 | + |
| 100 | +This approach works because: |
| 101 | +1. Sorting potions allows us to use binary search for efficient lookup |
| 102 | +2. For each spell, we need to find how many potions are strong enough |
| 103 | +3. Binary search finds the minimum potion index that satisfies the condition |
| 104 | +4. All potions from that index to the end will also satisfy the condition |
| 105 | + |
| 106 | +--- |
| 107 | + |
| 108 | +## Dry Run (Binary Search) |
| 109 | +Example Input: `spells = [5,1,3], potions = [1,2,3,4,5], success = 7` |
| 110 | + |
| 111 | +Sorted potions: `[1,2,3,4,5]` |
| 112 | + |
| 113 | +Step-by-step execution: |
| 114 | +- For spell=5: Find smallest index where potions[mid] * 5 >= 7 |
| 115 | + - potions[2] * 5 = 3 * 5 = 15 >= 7 ✓ |
| 116 | + - potions[1] * 5 = 2 * 5 = 10 >= 7 ✓ |
| 117 | + - potions[0] * 5 = 1 * 5 = 5 < 7 ✗ |
| 118 | + - First successful index = 1, pairs = 5 - 1 = 4 |
| 119 | +- For spell=1: Find smallest index where potions[mid] * 1 >= 7 |
| 120 | + - potions[4] * 1 = 5 < 7 ✗ |
| 121 | + - potions[3] * 1 = 4 < 7 ✗ |
| 122 | + - potions[2] * 1 = 3 < 7 ✗ |
| 123 | + - potions[1] * 1 = 2 < 7 ✗ |
| 124 | + - potions[0] * 1 = 1 < 7 ✗ |
| 125 | + - First successful index = 5, pairs = 5 - 5 = 0 |
| 126 | +- For spell=3: Find smallest index where potions[mid] * 3 >= 7 |
| 127 | + - potions[2] * 3 = 3 * 3 = 9 >= 7 ✓ |
| 128 | + - potions[1] * 3 = 2 * 3 = 6 < 7 ✗ |
| 129 | + - First successful index = 2, pairs = 5 - 2 = 3 |
| 130 | + |
| 131 | +Final Answer = `[4,0,3]` |
| 132 | + |
| 133 | +--- |
| 134 | + |
| 135 | +## Solution (Binary Search) |
| 136 | +```java |
| 137 | +class Solution { |
| 138 | + public int[] successfulPairs(int[] spells, int[] potions, long success) { |
| 139 | + |
| 140 | + Arrays.sort(potions); |
| 141 | + int m = potions.length; |
| 142 | + int n = spells.length; |
| 143 | + |
| 144 | + int[] results = new int[n]; |
| 145 | + |
| 146 | + for (int i = 0; i < n; i++) { |
| 147 | + int currentSpell = spells[i]; |
| 148 | + |
| 149 | + int low = 0; |
| 150 | + int high = m - 1; |
| 151 | + int firstSuccessfulPotionIndex = m; |
| 152 | + |
| 153 | + while (low <= high) { |
| 154 | + int mid = low + (high - low) / 2; |
| 155 | + if ((long) potions[mid] * currentSpell >= success) { |
| 156 | + firstSuccessfulPotionIndex = mid; |
| 157 | + high = mid - 1; |
| 158 | + } else { |
| 159 | + low = mid + 1; |
| 160 | + } |
| 161 | + } |
| 162 | + |
| 163 | + results[i] = m - firstSuccessfulPotionIndex; |
| 164 | + } |
| 165 | + |
| 166 | + return results; |
| 167 | + } |
| 168 | +} |
| 169 | +``` |
| 170 | + |
| 171 | +--- |
| 172 | + |
| 173 | +## Time and Space Complexity (Binary Search) |
| 174 | +- **Time Complexity:** O((n + m) * log m) - O(m log m) for sorting potions + O(n log m) for binary searches |
| 175 | +- **Space Complexity:** O(1) - excluding the output array, only using constant extra space |
0 commit comments