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; } }
分类:
leetcode题目
标签:
leetcode题等级-中等
, 二分查找
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】