2300. 咒语和药水的成功对数

题目:

 

思路:

【1】这种其实暴力处理都是可以的,因为本质上两个数组都是无序的,而基于O(N^2),用排序加二分的方式其实可以优化到O(N*longN)

代码展示:

【1】更优的方式(其实就是分了情况进行处理,时间复杂度为O(N))

复制代码
//时间4 ms 击败 100%
//内存60.2 MB 击败 11.45%
class Solution {
    public int[] successfulPairs(int[] spells, int[] potions, long success) {
        int min = spells[0];
        
        int max = min;
        for (int i = 1; i < spells.length; i++) {
            int spell = spells[i];
            if (min > spell) {
                min = spell;
            } else if (max < spell) {
                max = spell;
            }
        }
        --success;
        // 小于等于minPotion的药水无法与任何咒语组合成功,大于maxPotion的药水可以与任意咒语组合成功
        int minPotion = (int)Math.min(100000, success / max), maxPotion = (int)Math.min(100000, success / min);
        if (minPotion == maxPotion) {
            int cnt = 0;
            for (int i = 0; i < potions.length; i++) {
                if (potions[i] > maxPotion) {
                    ++cnt;
                }
            }
            Arrays.fill(spells, cnt);
            return spells;
        }

        int[] arr = new int[max - --min];
        for (int potion : potions) {
            if (potion > minPotion) {
                ++arr[potion > maxPotion ? 0 : (int)(success / potion) - min];
            }
        }
        ++min;
        // 执行到此处时,值为 i 的咒语可组合成功的药水数为 arr 中下标小于等于 i 的元素之和
        // 下面求前缀和后,值为 i 的咒语可组合成功的药水数为 arr[i]
        for (int i = 1; i < arr.length; i++) {
            arr[i] += arr[i - 1];
        }
        potions = arr;
        
        int[] r = new int[spells.length];
        for (int i = 0; i < spells.length; i++) {
            r[i] = potions[spells[i] - min];
        }
        return r;
    }
}
复制代码

 

【2】普通的二分方式(你会发现拆分成两个方法深入一层进行调用的时候远比都放在一个方法里面要快,当然第二份里面还会进行截枝操作,所以第三份更是拿来作比对)

复制代码
//时间47 ms 击败 52.42%
//内存55.4 MB 击败 54.10%
class Solution {
    public int[] successfulPairs(int[] spells, int[] potions, long success) {
        int[] res = new int[spells.length];
        Arrays.sort(potions);
        for (int i = 0; i < spells.length;i++){
            long s = spells[i]; //必须要转发为long类型,不然超范围
            int count = 0 , left = 0, right = potions.length;
            while (left < right){
                int mid = (right - left)/2 + left;
                if (s*potions[mid] >= success){
                    right = mid;
                }else {
                    left = mid + 1;
                }
            }
            res[i] = potions.length - left;
        }
        return res;
    }
}

//时间27 ms 击败 98.42%
//内存60.1 MB 击败 13.72%
class Solution {
    public int[] successfulPairs(int[] spells, int[] potions, long success) {
        int[] ans=new int[spells.length];
        Arrays.sort(potions);
        long[] arr=new long[potions.length];//必须要转发为long类型,不然超范围
        for (int i = 0; i < arr.length; i++) {
            arr[i]=potions[i];
        }
        for (int i = 0; i < spells.length; i++) {
            //二分查找arr[index] * spell[i]>=target的第一个数据
            int index=search(arr,spells[i],success);
            ans[i]=potions.length-index;
        }
        
        return ans;
    }
    //二分查找arr[index] * spell[i]>=target的第一个数据
    private int search(long[] arr,long x,long target) {
        if(arr[arr.length-1]*x<target) return arr.length;//对边界进行处理
        int l=0,r=arr.length-1;
        while (l<r) {
            int mid=(l+r)>>1;
            if(arr[mid]*x>=target) r=mid;
            else l=mid+1;
        }
        return r;
    }
}

//时间31 ms击败 85.69%
//内存60.3 MB 击败 9.87%
class Solution {
    public int[] successfulPairs(int[] spells, int[] potions, long success) {
        int[] ans=new int[spells.length];
        Arrays.sort(potions);
        long[] arr=new long[potions.length];//必须要转发为long类型,不然超范围
        for (int i = 0; i < arr.length; i++) {
            arr[i]=potions[i];
        }
        for (int i = 0; i < spells.length; i++) {
            //二分查找arr[index] * spell[i]>=target的第一个数据
            int index=search(arr,spells[i],success);
            ans[i]=potions.length-index;
        }
        
        return ans;
    }
    //二分查找arr[index] * spell[i]>=target的第一个数据
    private int search(long[] arr,long x,long target) {
        // if(arr[arr.length-1]*x<target) return arr.length;//对边界进行处理
        int l=0,r=arr.length;
        while (l<r) {
            int mid=(l+r)>>1;
            if(arr[mid]*x>=target) r=mid;
            else l=mid+1;
        }
        return r;
    }
}
复制代码

 

posted @   忧愁的chafry  阅读(23)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示