LeetCode 每日一题 2025/7/7-2025/7/13
记录了初步解题思路 以及本地实现代码;并不一定为最优 也希望大家能一起探讨 一起进步
目录
- 7/7 1353. 最多可以参加的会议数目
- 7/8 1751. 最多可以参加的会议数目 II
- 7/9 3439. 重新安排会议得到最多空余时间 I
- 7/10 3440. 重新安排会议得到最多空余时间 II
- 7/11 3169. 无需开会的工作日
- 7/12 1900. 最佳运动员的比拼回合
- 7/13
7/7 1353. 最多可以参加的会议数目
将会议按照开始时间从小到大分组 在组内尽量选择结束日期早的选择
def maxEvents(events):""":type events: List[List[int]]:rtype: int"""import heapqmx=max(e[1] for e in events)grp=[[] for _ in range(mx+1)]for e in events:grp[e[0]].append(e[1])ans=0h=[]for i,g in enumerate(grp):while h and h[0]<i:heapq.heappop(h)for end in g:heapq.heappush(h, end)if h:ans+=1heapq.heappop(h)return ans
7/8 1751. 最多可以参加的会议数目 II
根据结束时间先后排序
dp[i][j]表示前i个会议选择j个最大价值和
i不参加
dp[i][j]=dp[i-1][j]
i参加 假设在[1,starti-1]内有p个会议
dp[i][j]=dp[p][j-1]+value
二分查找结束时间早于starti的会议数目
def maxValue(events, k):""":type events: List[List[int]]:type k: int:rtype: int"""import bisectevents.sort(key=lambda x:x[1])n=len(events)dp=[[0]*(k+1) for _ in range(n+1)]for i,(start,end,v) in enumerate(events):p=bisect.bisect_left(events, start,hi=n-1,key=lambda x:x[1])for j in range(1,k+1):dp[i+1][j]=max(dp[i][j],dp[p][j-1]+events[i][2])return dp[n][k]
7/9 3439. 重新安排会议得到最多空余时间 I
转换为合并相邻的k+1个空余时间块
滑动长度为k+1的窗口
def maxFreeTime(eventTime, k, startTime, endTime):""":type eventTime: int:type k: int:type startTime: List[int]:type endTime: List[int]:rtype: int"""n=len(startTime)free=[0]*(n+1)free[0]=startTime[0]free[-1]=eventTime-endTime[-1]for i in range(1,n):free[i]=startTime[i]-endTime[i-1]ans=0cur=0for i,f in enumerate(free):cur+=fif i<k:continueans=max(ans,cur)cur-=free[i-k]return ans
7/10 3440. 重新安排会议得到最多空余时间 II
只能移动一次会议 就是将相邻的两个空余时间合并
最理想的情况 两个空余时间中间的会议可以安排到另一个空余时间内
得到结果就是两个空余时间相加再加上中间的会议时间
否则只能是两个空余时间相加
为了判断是否可以放入会议 记录前三大的空位
def maxFreeTime(eventTime, startTime, endTime):""":type eventTime: int:type startTime: List[int]:type endTime: List[int]:rtype: int"""n=len(startTime)def find(i):if i==0:return startTime[0]if i==n:return eventTime-endTime[-1]return startTime[i]-endTime[i-1]a,b,c=0,-1,-1for i in range(1,n+1):v=find(i)if v>find(a):a,b,c=i,a,belif b<0 or v>find(b):b,c=i,belif c<0 or v>find(c):c=ians=0for i,(s,e) in enumerate(zip(startTime,endTime)):v=e-sif i!=a and i+1!=a and v<=find(a) or (i!=b and i+1!=b and v<=find(b)) or v<=find(c):ans=max(ans,find(i)+v+find(i+1))else:ans=max(ans,find(i)+find(i+1))return ans
7/11 3169. 无需开会的工作日
将开会起始日期从小到大排序 合并重叠的会议
工作日减去开会的天数
def countDays(days, meetings):""":type days: int:type meetings: List[List[int]]:rtype: int"""meetings.sort()l,r=1,0for m in meetings:if m[0]>r:days-=r-l+1l=m[0]r=max(r,m[1])days-=r-l+1return days
7/12 1900. 最佳运动员的比拼回合
参考:https://leetcode.cn/problems/the-earliest-and-latest-rounds-where-players-compete/solutions/825860/dpmei-ju-xia-yi-lun-liang-ming-xuan-shou-okfu/?envType=daily-question&envId=2025-07-12
def earliestAndLatest(n, firstPlayer, secondPlayer):""":type n: int:type firstPlayer: int:type secondPlayer: int:rtype: List[int]"""if firstPlayer + secondPlayer == n + 1:return [1, 1]if firstPlayer + secondPlayer > n + 1:firstPlayer, secondPlayer = n + 1 - secondPlayer, n + 1 - firstPlayerdef calc_earliest_rounds(n):res = 1if firstPlayer + secondPlayer <= (n + 1) // 2:while firstPlayer + secondPlayer <= (n + 1) // 2:res += 1n = (n + 1) // 2if secondPlayer - firstPlayer > 1:return res + 1if secondPlayer - firstPlayer == 1:res += 1n = (n + 1) // 2while n % 2 > 0:res += 1n = (n + 1) // 2return resif secondPlayer <= (n + 1) // 2:return res + 1if secondPlayer - firstPlayer == 2:res += 1n = (n + 1) // 2while n % 2 > 0:res += 1n = (n + 1) // 2return resif firstPlayer % 2 == 0 and firstPlayer + secondPlayer == n:res += 1return res + 1earliest = calc_earliest_rounds(n)latest = min((n - 1).bit_length(), n + 1 - secondPlayer)return [earliest, latest]
7/13