咒语和药水的成功对数
给你两个正整数数组 spells 和 potions ,长度分别为 n 和 m ,其中 spells[i] 表示第 i 个咒语的能量强度,potions[j] 表示第 j 瓶药水的能量强度。
同时给你一个整数 success 。一个咒语和药水的能量强度 相乘 如果 大于等于 success ,那么它们视为一对 成功 的组合。
请你返回一个长度为 n 的整数数组 pairs,其中 pairs[i] 是能跟第 i 个咒语成功组合的 药水 数目。
示例 1:
输入:spells = [5,1,3], potions = [1,2,3,4,5], success = 7
输出:[4,0,3]
解释:
-第 0 个咒语:5 * [1,2,3,4,5] = [5,10,15,20,25] 。总共 4 个成功组合。
-第 1 个咒语:1 * [1,2,3,4,5] = [1,2,3,4,5] 。总共 0 个成功组合。
-第 2 个咒语:3 * [1,2,3,4,5] = [3,6,9,12,15] 。总共 3 个成功组合。
所以返回 [4,0,3] 。
示例 2:
输入:spells = [3,1,2], potions = [8,5,8], success = 16
输出:[2,0,2]
解释:
-第 0 个咒语:3 * [8,5,8] = [24,15,24] 。总共 2 个成功组合。
-第 1 个咒语:1 * [8,5,8] = [8,5,8] 。总共 0 个成功组合。
-第 2 个咒语:2 * [8,5,8] = [16,10,16] 。总共 2 个成功组合。
所以返回 [2,0,2] 。
提示:
n == spells.length
m == potions.length
1 <= n, m <= 105
1 <= spells[i], potions[i] <= 105
1 <= success <= 1010
题解
根据题目要求,我们需要遍历数组 spells ,然后找到数组 potions 中满足条件的个数并记录下来
如果直接枚举,时间复杂度是 n^2 有点大
所以我们可以优化 找到数组 potions 中满足条件的个数 这一步骤
题目要求 数组的中一对数据的积 >= success 那么对于每一次遍历的 spells[i],我们需要查找数组 potions 中大于 (success-1)/spells[i] 的数据个数
我们不妨将数组 potions 进行排序,然后查找到数组中第一个大于 (success-1)/spells[i] 的数据对应的下标 r ,由于排序了,所以对应的下标 r 以及之后的数组中的数据都满足条件,那么满足条件的总个数就是 potionsSize - r 个
对于有序数组的查找,我们可以使用二分查找
代码如下↓
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* successfulPairs(int* spells, int spellsSize, int* potions, int potionsSize, long long success, int* returnSize) {
int compare(const void* a,const void* b)
{
return *(int*)a - *(int*)b;
}
*returnSize=spellsSize;
int* arr = (int*)malloc(sizeof(int)*spellsSize);
qsort(potions,potionsSize,sizeof(int),compare);
for(int i=0;i<spellsSize;i++)
{
long long x=(success-1)/spells[i];
if(potions[potionsSize-1]<=x)
{
arr[i]=0;
}
else
{
int l=0,r=potionsSize-1;
while(l<r)
{
int mid=(l+r)/2;
if(potions[mid]>x)
{
r=mid;
}
else
{
l=mid+1;
}
}
arr[i]=potionsSize-r;
}
}
return arr;
}