Question
You are given two positive integer arrays spells
and potions
, of length n
and m
respectively, where spells[i]
represents the strength of the i<sup>th</sup>
spell and potions[j]
represents the strength of the j<sup>th</sup>
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 i<sup>th</sup>
spell.
Solution 1 排序+二分搜索。同时记录success与spells[i]的比值来减小计算量。
排序 首先对potions[]进行排序,这样可以使用二分搜索查找分界值。 数组scales[]记录success与spells[i]的比值,以此为界大于等于scales[i]的位置都可以计入ret[]数组。
二分搜索 这里有一些tricky。
由于Arrays.binarySearch()方法无法返回重复的数字,因此在搜索时我们将查找值scale减去一个小值,保证在搜索时一定返回负值。(查找值的插入位置的负数-1) 将ret[i]记录为potions[]的总数减去正确的插入位置即可。
Code 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Solution { public int [] successfulPairs(int [] spells, int [] potions, long success) { int [] ret = new int [spells.length]; Arrays.sort(potions); double [] scales = new double [potions.length]; for (int i = 0 ; i < potions.length; i++){ scales[i] = (double ) potions[i]; } for (int i = 0 ; i < spells.length; i++){ double scale = (double ) success / spells[i] - 0.000001 ; int index = Arrays.binarySearch(scales, scale); ret[i] = potions.length + (index + 1 ); } return ret; } }
Solution 2 由于Arrays.binarySearch()无法正确的搜索有重复元素的数组,因此采用辅助方法binarySearch()来搜索最左侧的下标。
直接在binarySearch()方法中查找target,比较的对象为spell和potions[i]的乘积。
为了搜寻重复的第一个元素,当遇到target时不直接返回,而是继续修改right的位置,直到left等于right。
如果未搜索到,则返回数组的总长度。
Code 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Solution { public int [] successfulPairs(int [] spells, int [] potions, long success) { int [] ret = new int [spells.length]; Arrays.sort(potions); for (int i = 0 ; i < spells.length; i++){ int index = binarySearch(potions, spells[i], success); ret[i] = potions.length - index; } return ret; } private int binarySearch (int [] potions, long spell, long target) { int left = 0 , right = potions.length - 1 ; while (left < right){ int mid = left + (right - left) / 2 ; if (potions[mid] * spell < target) left = mid + 1 ; else right = mid; } return potions[left] * spell < target ? potions.length : left; } }