楼主: Myron2017
跳转到指定楼层
上一主题 下一主题
收起左侧

刷题记录帖子

🔗
 楼主| Myron2017 2026-2-6 11:07:37 | 只看该作者
全局:
LC 1004. Max Consecutive Ones III

和上一道题目是类似的解法。
  1. class Solution:
  2.     def longestOnes(self, nums: List[int], k: int) -> int:
  3.         count_w = [0, 0]
  4.         left, right = 0, 0
  5.         max_len = 0

  6.         while right < len(nums):
  7.             count_w[nums[right]] += 1
  8.             len_w = right - left + 1
  9.             changes = len_w - count_w[1] # how many zeros needs to be changed

  10.             if changes <= k:
  11.                 # valid window, update max_len
  12.                 max_len = max(max_len, len_w)
  13.                 right += 1 # expand window
  14.             else:
  15.                 # invalid window, move window to right
  16.                 count_w[nums[left]] -= 1
  17.                 left += 1
  18.                 right += 1
  19.         return max_len


  20.         
复制代码
回复

使用道具 举报

🔗
 楼主| Myron2017 2026-2-6 11:35:53 | 只看该作者
全局:
LC 3634. Minimum Removals to Balance Array

删除最少 = 保留最多
目标:max ≤ k × min
转化:找最长的满足条件的子数组


一句话总结
排序 + 滑动窗口找最长满足 max ≤ k×min 的子数组,删除数 = n - 最长长度
  1. class Solution:
  2.     def minRemoval(self, nums: List[int], k: int) -> int:
  3.         n = len(nums)
  4.         if n == 1:
  5.             return 0
  6.         
  7.         nums.sort()
  8.         
  9.         left = 0
  10.         max_len = 0
  11.         
  12.         for right in range(n):
  13.             # 不合法时收缩:max > k × min
  14.             while left <= right and nums[right] > k * nums[left]:
  15.                 left += 1
  16.             
  17.             # 窗口合法
  18.             if left <= right:
  19.                 max_len = max(max_len, right - left + 1)
  20.         
  21.         return n - max_len
复制代码
回复

使用道具 举报

🔗
 楼主| Myron2017 2026-2-6 11:47:17 | 只看该作者
全局:
本帖最后由 Myron2017 于 2026-2-5 21:50 编辑
LC 1482. Minimum Number of Days to Make m Bouquets核心思路

单调性 → 二分搜索天数 → 每次检查能否做出 m 个花束

二分搜索天数,每次检查该天能否凑出 m 个 k 朵连续花的花束,关键是遇到未开的花要重置连续计数。
  1. class Solution:
  2.     def minDays(self, bloomDay: List[int], m: int, k: int) -> int:
  3.         n = len(bloomDay)
  4.         
  5.         # 不可能的情况
  6.         if m * k > n: return -1
  7.         
  8.         # 二分搜索天数
  9.         left, right = min(bloomDay), max(bloomDay)
  10.         
  11.         while left < right:
  12.             mid = (left + right) // 2
  13.             
  14.             if self.canMake(bloomDay, mid, m, k):
  15.                 right = mid  # 可以做出,尝试更少天数
  16.             else:
  17.                 left = mid + 1  # 需要更多天数
  18.         
  19.         return left
  20.    
  21.     def canMake(self, bloomDay: List[int], day: int, m: int, k: int) -> bool:
  22.         """检查第 day 天能否做出 m 个花束"""
  23.         bouquets = 0
  24.         flowers = 0
  25.         
  26.         for bloom in bloomDay:
  27.             if bloom <= day:
  28.                 flowers += 1
  29.                 if flowers == k:
  30.                     bouquets += 1
  31.                     flowers = 0
  32.                     if bouquets >= m:  # 提前返回优化
  33.                         return True
  34.             else:
  35.                 flowers = 0
  36.         
  37.         return bouquets >= m
复制代码
回复

使用道具 举报

🔗
 楼主| Myron2017 2026-2-6 12:28:07 | 只看该作者
全局:
LC 1011. Capacity To Ship Packages Within D Days

这道题用二分搜索船的最小容量。
下界是 max(weights),上界是 sum(weights)。


因为每个包裹不能给拆分了,所以船最小必须比最大的包裹大!

对每个容量,用贪心模拟装货,统计需要多少天,判断是否 ≤ days。
  1. class Solution:
  2.     def shipWithinDays(self, weights: List[int], days: int) -> int:


  3.         def canShipWithinDays(capacity):
  4.             used_days = 0
  5.             curr_sum_weight = 0
  6.             for w in weights:
  7.                 curr_sum_weight += w
  8.                 if curr_sum_weight > capacity:
  9.                     used_days += 1
  10.                     if used_days > days: return False
  11.                     curr_sum_weight = w
  12.             used_days += 1 # update 1 due to remaining packages
  13.             return used_days <= days
  14.         
  15.         left, right = max(weights), sum(weights)

  16.         while left < right:
  17.             mid = (left + right) // 2
  18.             if canShipWithinDays(mid):
  19.                 right = mid
  20.             else:
  21.                 left = mid + 1
  22.         
  23.         return left


  24.         
复制代码
回复

使用道具 举报

🔗
 楼主| Myron2017 2026-2-6 12:41:08 | 只看该作者
全局:
LC 1283. Find the Smallest Divisor Given a Threshold
  1. class Solution:
  2.     def smallestDivisor(self, nums: List[int], threshold: int) -> int:

  3.         def isSumUnderThreshold(divisor):
  4.             res = 0
  5.             for num in nums:
  6.                 res += math.ceil(num / divisor)
  7.             return res <= threshold

  8.         left, right = 1, max(nums)

  9.         while left < right:
  10.             mid = (left + right) // 2
  11.             if isSumUnderThreshold(mid):
  12.                 right = mid
  13.             else:
  14.                 left = mid + 1
  15.         return left

  16.         
复制代码
回复

使用道具 举报

🔗
 楼主| Myron2017 2026-2-7 00:22:12 | 只看该作者
全局:
LC 1552. Magnetic Force Between Two Balls

三句话总结(1552 Magnetic Force)

1️⃣ 这道题是最大化最小值问题,可以转化为:给定最小距离 d,是否能放下 m 个球。
2️⃣ 因为 d 越小越容易、越大越困难,check(d) 具有单调性,所以可以对答案进行二分搜索。
3️⃣ 在 check 中用贪心策略:始终把球放在能放的最左位置,并且每次都与上一次放球的真实坐标比较距离。
  1. class Solution:
  2.     def maxDistance(self, position: List[int], m: int) -> int:
  3.         """
  4.         整体思路:
  5.         1. 这是一道「最大化最小值」的问题,答案是最小磁力 d
  6.         2. 固定一个 d,可以用贪心判断是否能放下 m 个球(check(d))
  7.         3. 因为 d 越小越容易、d 越大越困难,check(d) 具有单调性
  8.         4. 对 d 进行二分搜索,找最大的可行 d
  9.         """

  10.         # 先排序,方便从左到右贪心放球
  11.         position.sort()
  12.         n = len(position)

  13.         def isDPossibleForMBall(d):
  14.             """
  15.             判断是否能保证任意两个球之间的距离 >= d
  16.             贪心策略:始终把球放在「能放的最左位置」
  17.             """
  18.             # 第一个球放在最左边的篮子
  19.             last_pos = position[0]
  20.             curr_ball_put = 1

  21.             # 从第二个篮子开始尝试放球
  22.             for i in range(1, n):
  23.                 # 当前位置和上一次放球的位置距离是否满足 d
  24.                 if position[i] - last_pos >= d:
  25.                     curr_ball_put += 1
  26.                     # 更新上一次放球的“坐标值”(不是索引)
  27.                     last_pos = position[i]

  28.                     # 已经放下 m 个球,提前返回
  29.                     if curr_ball_put >= m:
  30.                         return True

  31.             return False

  32.         # d 的搜索范围:
  33.         # 最小为 1,最大为最右和最左篮子的距离
  34.         left, right = 1, position[-1] - position[0]

  35.         # 二分查找「最大的可行 d」
  36.         while left < right:
  37.             # 取上中位数,避免死循环
  38.             mid = (left + right + 1) // 2

  39.             if isDPossibleForMBall(mid):
  40.                 # mid 可行,尝试更大的最小距离
  41.                 left = mid
  42.             else:
  43.                 # mid 不可行,缩小右边界
  44.                 right = mid - 1

  45.         return left
复制代码
回复

使用道具 举报

🔗
 楼主| Myron2017 2026-2-7 00:30:56 | 只看该作者
全局:
LC. 1891. Cutting Ribbons

类似上一题思路,还是最大可行值。

注意排除下,完全 cut 不出来彩带的情况!


You are given an integer array ribbons, where ribbons[i] represents the length of the ith ribbon, and an integer k. You may cut any of the ribbons into any number of segments of positive integer lengths, or perform no cuts at all.

For example, if you have a ribbon of length 4, you can:
Keep the ribbon of length 4,
Cut it into one ribbon of length 3 and one ribbon of length 1,
Cut it into two ribbons of length 2,
Cut it into one ribbon of length 2 and two ribbons of length 1, or
Cut it into four ribbons of length 1.
Your task is to determine the maximum length of ribbon, x, that allows you to cut at least k ribbons, each of length x. You can discard any leftover ribbon from the cuts. If it is impossible to cut k ribbons of the same length, return 0.



Example 1:

Input: ribbons = [9,7,5], k = 3
Output: 5
Explanation:
- Cut the first ribbon to two ribbons, one of length 5 and one of length 4.
- Cut the second ribbon to two ribbons, one of length 5 and one of length 2.
- Keep the third ribbon as it is.
Now you have 3 ribbons of length 5.
Example 2:

Input: ribbons = [7,5,9], k = 4
Output: 4
Explanation:
- Cut the first ribbon to two ribbons, one of length 4 and one of length 3.
- Cut the second ribbon to two ribbons, one of length 4 and one of length 1.
- Cut the third ribbon to three ribbons, two of length 4 and one of length 1.
Now you have 4 ribbons of length 4.
Example 3:

Input: ribbons = [5,7,9], k = 22
Output: 0
Explanation: You cannot obtain k ribbons of the same positive integer length.


Constraints:

1 <= ribbons.length <= 105
1 <= ribbons[i] <= 105
1 <= k <= 109
  1. class Solution:
  2.     def maxLength(self, ribbons: List[int], k: int) -> int:
  3.         """
  4.         if X is very samll, True
  5.         so X has a limit, X max is max(ribbons)
  6.         check(x): for each robion, cut to x as much as possible, and then see if k ribbons satisfiy with length x
  7.         """
  8.         if sum(ribbons) < k: return 0

  9.         def isKRibbonsPossible(x):
  10.             curr_x_ribbons = 0
  11.             for r in ribbons:
  12.                 if r >= x:
  13.                     curr_x_ribbons += r//x
  14.                 if curr_x_ribbons >= k: return True
  15.             return False
  16.         
  17.         left, right = 1, max(ribbons)
  18.         while left < right:
  19.             mid = (left + right + 1) // 2
  20.             if isKRibbonsPossible(mid):
  21.                 left = mid
  22.             else:
  23.                 right = mid - 1
  24.         return left
复制代码
回复

使用道具 举报

🔗
 楼主| Myron2017 2026-2-7 00:37:43 | 只看该作者
全局:
LC. 2226. Maximum Candies Allocated to K Children

Same questions
  1. class Solution:
  2.     def maximumCandies(self, candies: List[int], k: int) -> int:
  3.         if sum(candies) < k: return 0

  4.         """

  5.         Assume each child get d candies

  6.         then for each pile of candies, arrange it into subpiles of d candies
  7.         compare with k

  8.         binary search for largest possible d

  9.         """

  10.         def isPossible(d):
  11.             curr_sub_piles = 0
  12.             for c in candies:
  13.                 if c >= d:
  14.                     curr_sub_piles += c//d
  15.                 if curr_sub_piles >= k: return True
  16.             return False
  17.         
  18.         left, right = 1, max(candies)

  19.         while left < right:
  20.             mid = (left + right + 1) // 2
  21.             if isPossible(mid):
  22.                 left = mid
  23.             else:
  24.                 right = mid - 1
  25.         return left
  26.         

  27.         
复制代码
回复

使用道具 举报

🔗
 楼主| Myron2017 2026-2-7 02:03:35 | 只看该作者
全局:
LC 410. Split Array Largest Sum

✅ 总结经验

本题核心思想

题目要求把数组分成 k 段,使得每段的和的 最大值最小化 → 这是一个典型的 二分答案(binary search on answer)问题。

核心是定义一个 check 函数:给定一个候选最大段和 d,判断能否把数组切成 ≤ k 段,每段和 ≤ d。

check 函数设计

从左往右累加数组元素,如果当前段加上新元素超过 d,则开新段。

如果最终段数 ≤ k,则 d 是可行的;否则 d 太小,不可行。

二分思路

左边界 left = max(nums):最小可行的 d 不可能小于数组最大元素。

右边界 right = sum(nums):最大可行的 d 不可能超过整个数组和。

每次取 mid = (left + right) // 2,判断 mid 是否可行:

可行 → 尝试更小的 d → right = mid

不可行 → d 太小 → left = mid + 1

返回 left,就是最小的可行最大段和。

边界注意点

数组只有一个元素或 k = 1 的特殊情况直接返回。

check 函数计数从 1 开始,因为至少有一段。
  1. class Solution:
  2.     def splitArray(self, nums: List[int], k: int) -> int:
  3.         """
  4.         思路:
  5.         - 我们要找到数组分成 k 段时,最大段和的最小值。
  6.         - 使用二分答案法:二分搜索最大段和 d 的最小可行值。
  7.         - check(d) 函数判断能否把数组切成 <= k 段,每段和 <= d。
  8.         """

  9.         # 边界情况
  10.         if k == 1:  # 只能一段,最大段和就是数组总和
  11.             return sum(nums)
  12.         if len(nums) == 1:  # 数组只有一个元素,直接返回它
  13.             return nums[0]

  14.         def check(d: int) -> bool:
  15.             """
  16.             判断是否存在 <= k 段,使得每段和 <= d
  17.             """
  18.             count_subarr = 1  # 当前已经使用的段数,从 1 开始
  19.             curr_subarry_sum = 0  # 当前段的累加和
  20.             for num in nums:
  21.                 if curr_subarry_sum + num > d:
  22.                     # 超过当前最大段和,开新段
  23.                     count_subarr += 1
  24.                     curr_subarry_sum = num  # 新段初始值为当前元素
  25.                 else:
  26.                     curr_subarry_sum += num
  27.                 if count_subarr > k:  # 已经超过 k 段 → d 不可行
  28.                     return False
  29.             return True  # 能在 k 段内完成 → d 可行

  30.         # 二分搜索最大段和的最小可行值
  31.         left = max(nums)   # d 最小不能小于数组最大元素
  32.         right = sum(nums)  # d 最大不会超过整个数组和

  33.         while left < right:
  34.             mid = (left + right) // 2  # 候选最大段和
  35.             if check(mid):
  36.                 right = mid  # mid 可行,尝试更小的 d
  37.             else:
  38.                 left = mid + 1  # mid 不可行,d 太小

  39.         return left  # 最小可行的最大段和
复制代码
回复

使用道具 举报

🔗
 楼主| Myron2017 2026-2-7 05:10:02 来自APP | 只看该作者
全局:
LC 2943. Maximize Area of Square Hole in Grid

这道题目,其实说穿了很简单。 题目说得需要理解,面试的时候可以多问问面试官。

当然了,这个我也能理解,就是在考察所谓的 Problem Solving Ability,不过这太无语了。

移除 k 条连续的条 → 形成 k+1 的间隙 → 正方形取两个方向的 min!





回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号
隐私提醒:
  • ☑ 禁止发布广告,拉群,贴个人联系方式:找人请去🔗同学同事飞友,拉群请去🔗拉群结伴,广告请去🔗跳蚤市场,和 🔗租房广告|找室友
  • ☑ 论坛内容在发帖 30 分钟内可以编辑,过后则不能删帖。为防止被骚扰甚至人肉,不要公开留微信等联系方式,如有需求请以论坛私信方式发送。
  • ☑ 干货版块可免费使用 🔗超级匿名:面经(美国面经、中国面经、数科面经、PM面经),抖包袱(美国、中国)和录取汇报、定位选校版
  • ☑ 查阅全站 🔗各种匿名方法

本版积分规则

>
快速回复 返回顶部 返回列表