Successful Pairs of Spells and Potions
Successful Pairs of Spells and Potions Problem
Problem
You are given two positive integer arrays spells and potions, of length n and m respectively, where spells[i] represents the strength of the ith spell and potions[j] represents the strength of the jth potion.
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.
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.
Examples
Example 1:
Input:
spells = [5,1,3], potions = [1,2,3,4,5], success = 7
Output:
[4,0,3]
Explanation:
- 0th spell: 5 * [1,2,3,4,5] = [5,**10**,**15**,**20**,**25**]. 4 pairs are successful.
- 1st spell: 1 * [1,2,3,4,5] = [1,2,3,4,5]. 0 pairs are successful.
- 2nd spell: 3 * [1,2,3,4,5] = [3,6,**9**,**12**,**15**]. 3 pairs are successful.
Thus, [4,0,3] is returned.
Example 2:
Input:
spells = [3,1,2], potions = [8,5,8], success = 16
Output:
[2,0,2]
Explanation:
- 0th spell: 3 * [8,5,8] = [**24**,15,**24**]. 2 pairs are successful.
- 1st spell: 1 * [8,5,8] = [8,5,8]. 0 pairs are successful.
- 2nd spell: 2 * [8,5,8] = [**16**,10,**16**]. 2 pairs are successful.
Thus, [2,0,2] is returned.
Solution
Question reduces to finding no of potions for each spell which have product greater than success where product is (each spell * potions[i]). Now decision is whether to keep the potions array sorted or not.
Method 1 – Brute Force
Intuition
The most straightforward approach is to check every possible pair of spell and potion. For each spell, we iterate through all potions and count how many pairs have a product greater than or equal to the given success threshold. This method does not require sorting and works directly with the input arrays.
Approach
- For each spell in the
spellsarray:- Loop through every potion in the
potionsarray. - Multiply the spell and potion values.
- If the product is greater than or equal to
success, increment the count for that spell.
- Loop through every potion in the
- Store the count for each spell in the result array.
- Return the result array after processing all spells.
Complexity
- ⏰ Time complexity:
O(n * m), wherenis the number of spells andmis the number of potions. We check every possible pair. - 🧺 Space complexity:
O(n), for the result array storing the count for each spell.
Method 2 – Sort Potions and Use Binary Search
Intuition
To improve efficiency, we sort the potions array. For each spell, we want to count how many potions can form a successful pair (i.e., spell * potion >= success). Since the potions are sorted, we can use binary search to quickly find the first potion that meets the threshold for each spell.
Approach
- Sort the
potionsarray in non-decreasing order. - For each spell:
- Use binary search to find the smallest index
isuch thatspell * potions[i] >= success. - The number of successful pairs for this spell is
potions.length - i.
- Use binary search to find the smallest index
- Store the result for each spell in the answer array.
- Return the answer array.
This approach leverages the sorted order of potions to reduce the search for each spell from linear to logarithmic time.
Code
C++
#include <vector>
#include <algorithm>
using namespace std;
class Solution {
public:
vector<int> successfulPairs(vector<int>& spells, vector<int>& potions, long long success) {
sort(potions.begin(), potions.end());
int m = potions.size();
vector<int> res;
for (int spell : spells) {
int left = 0, right = m;
while (left < right) {
int mid = left + (right - left) / 2;
if ((long long)spell * potions[mid] < success) left = mid + 1;
else right = mid;
}
res.push_back(m - left);
}
return res;
}
};
Go
import (
"sort"
)
func successfulPairs(spells []int, potions []int, success int64) []int {
sort.Ints(potions)
m := len(potions)
res := make([]int, len(spells))
for i, spell := range spells {
left, right := 0, m
for left < right {
mid := left + (right-left)/2
if int64(spell)*int64(potions[mid]) < success {
left = mid + 1
} else {
right = mid
}
}
res[i] = m - left
}
return res
}
Java
import java.util.*;
class Solution {
public int[] successfulPairs(int[] spells, int[] potions, long success) {
Arrays.sort(potions);
int m = potions.length;
int[] res = new int[spells.length];
for (int i = 0; i < spells.length; i++) {
int left = 0, right = m;
while (left < right) {
int mid = left + (right - left) / 2;
if ((long)spells[i] * potions[mid] < success) left = mid + 1;
else right = mid;
}
res[i] = m - left;
}
return res;
}
}
Kotlin
class Solution {
fun successfulPairs(spells: IntArray, potions: IntArray, success: Long): IntArray {
potions.sort()
val m = potions.size
return spells.map { spell ->
var left = 0
var right = m
while (left < right) {
val mid = left + (right - left) / 2
if (spell.toLong() * potions[mid] < success) left = mid + 1
else right = mid
}
m - left
}.toIntArray()
}
}
Python
from bisect import bisect_left
class Solution:
def successfulPairs(self, spells: list[int], potions: list[int], success: int) -> list[int]:
potions.sort()
m = len(potions)
res = []
for spell in spells:
# Find the smallest index where spell * potion >= success
left, right = 0, m
while left < right:
mid = (left + right) // 2
if spell * potions[mid] < success:
left = mid + 1
else:
right = mid
res.append(m - left)
return res
Rust
impl Solution {
pub fn successful_pairs(spells: Vec<i32>, mut potions: Vec<i32>, success: i64) -> Vec<i32> {
potions.sort();
let m = potions.len();
spells.iter().map(|&spell| {
let (mut left, mut right) = (0, m);
while left < right {
let mid = left + (right - left) / 2;
if (spell as i64) * (potions[mid] as i64) < success {
left = mid + 1;
} else {
right = mid;
}
}
(m - left) as i32
}).collect()
}
}
TypeScript
function successfulPairs(spells: number[], potions: number[], success: number): number[] {
potions.sort((a, b) => a - b);
const m = potions.length;
return spells.map(spell => {
let left = 0, right = m;
while (left < right) {
const mid = Math.floor(left + (right - left) / 2);
if (spell * potions[mid] < success) left = mid + 1;
else right = mid;
}
return m - left;
});
}
Complexity
- ⏰ Time complexity:
O(n log m), wherenis the number of spells andmis the number of potions. Sorting potions takesO(m log m), and for each spell, binary search takesO(log m). - 🧺 Space complexity:
O(n), for the result array storing the count for each spell.