分发饼干之 双数组匹配问题 (双指针 or 二分)
文章目录
- 455.分发饼干
- 2410.运动员和训练师的最大匹配数
455.分发饼干


- 思路分析:根据
贪心策略,肯定是胃口g[i]匹配大于等于它的最小的饼干s[i],同时,还需要考虑,一个饼干只能给一个胃口,所以我们不能重复分配 - 由于涉及到
大小问题,所以,我们对数组g和s都先进行升序排序
二分思路来源
- 如果直接暴力求解,也就是对于孩子胃口
g[i],都在饼干数组中,重头开始遍历查找,那么时间复杂度会来到o(n^2),肯定是会超时的 - 考虑到我们的目标是对于每一个孩子的胃口
g[i]找到第一个还没被分配的>=g[i]的s[i],所以我们可以使用限制范围二分进行求解,在这里介绍这个bisect_left(a,x,lo=0,hi=len(a),可以通过lo和hi对于搜索的范围进行限定,其中总的范围是一个左闭右开的情况[0,len(a)) - 这里有一个提前终止的情况,也就是当较小的
g[i]都无法找到合适的s[j](也就是bisect_left方法返回数组长度),那么我们可以提前终止
import bisect
class Solution:def findContentChildren(self, g: List[int], s: List[int]) -> int:kid = len(g)bin = len(s)ans = 0 g.sort()s.sort()# 二分,但是有范围的二分ans = 0 curleft = 0 for i,c in enumerate(g):index = bisect.bisect_left(s,c,lo=curleft)if index == bin:breakans += 1curleft = index + 1return ans
双指针
- 考虑到暴力的做法的时间复杂度是
o(n^2),并且浪费的时间在于一些重复的查找过程,所以我们可以考虑使用双指针,记录当前的匹配到的孩子的下标,通过对饼干的一次遍历,我们就可以得到最终的结果 - 出发的角度,其实可以使用变量记录当前的孩子,然后遍历饼干,另一种思路是记录当前的饼干,然后遍历孩子。比较之后,发现第一种思路比较好,因为最终孩子的下标就是最终的答案
- 对于双指针的到底使用
cur变量记录什么,以及枚举孩子还是饼干,这个是不能搞错的,如何理解?我们的任务是给孩子分饼干,分配的策略是对于每一个孩子分配满足情况的最小的饼干,所以cur记录的是当前分配到的孩子,为了找到合适的饼干,所以我们需要枚举饼干
class Solution:def findContentChildren(self, g: List[int], s: List[int]) -> int:kid = len(g)bin = len(s)ans = 0 g.sort()s.sort()# 当前孩子的下标curkid = 0 for i,c in enumerate(s):if curkid < kid and g[curkid] <= c :curkid += 1return curkid
2410.运动员和训练师的最大匹配数
2410.运动员和训练师的最大匹配数


- 思路分析:这题和
分发饼干思路是一样的,当然这里我们的任务是给运动员分配训练师,所以cur记录的是当前分配到的运动员的下标,我们需要枚举训练师
class Solution:def matchPlayersAndTrainers(self, players: List[int], trainers: List[int]) -> int:n = len(players)players.sort()trainers.sort()curplayer = 0 for c in trainers:if curplayer < n and players[curplayer] <= c:curplayer+=1return curplayer
