控制上下限与规格上下限_二分查找找到上下限

控制上下限与规格上下限

This is originally posted at https://shawnlyu.com/algorithms/binary-search-find-upper-and-lower-bound/

这最初发布在https://shawnlyu.com/algorithms/binary-search-find-upper-and-lower-bound/

This post will introduce one specific application of Binary Search, i.e., when you are asked to find the upper or lower bound, or more precisely, when you need to find the maximum of the smallest value or the minimum of the largest value.

这篇文章将介绍Binary Search的一种特定应用,即,当您被要求查找上限或下限时,或更确切地说,当您需要查找最小值的最大值或最大值的最小值时

Binary Search is an algorithm to search for a target from a sorted array. It selects the middle element in the array and compares it against the target; if they are not equal, it eliminates one half of the array and keeps searching the other half in the same manner(Wikipedia).

二进制搜索是一种从排序数组中搜索目标的算法。 它选择数组中的中间元素,并将其与目标进行比较; 如果它们不相等,则消除数组的一半,并以相同的方式继续搜索另一半(维基百科)。

The most basic application of it is to find a number or a position from an array. Some practices could be found on Leetcode:

它的最基本应用是从数组中查找数字或位置。 在Leetcode上可以找到一些做法:

Another popular case to apply is when you are asked to find the maximum of the smallest value or the minimum of the largest value. Let’ take 410. Split Array Largest Sum from Leetcode as an example to illustrate how to deal with this kind of problem.

另一种流行的情况是,当要求您找到最小值的最大值或最大值的最小值时。 让我们以410. Leetcode中的最大拆分​​数组为例来说明如何处理此类问题。

如何搜寻 (How to search)

Search space

搜索空间

The search space would be from the maximum of the input nums, when m=len(nums), to the sum of nums, when m=1.

搜索空间将从输入nums的最大值(当m=len(nums)nums之和(当m=1

Search strategy

搜索策略

Each time we would pick the middle element mid of the search space as our threshold, and calculate the number of subarrays count while making sure that the sum of each subarray does not exceed mid. If count>m, it means we should increase mid to reduce the number of subarrays; else if count<=m, it means we can decrease mid to increase the number of subarrays, but mid is still qualified.

每一次我们会选择中间元素mid为我们的门槛搜索空间,并计算子阵列的数量count ,同时确保每个子阵列的总和不超过mid 。 如果count>m ,则意味着我们应该增加mid以减少子数组的数量; 否则,如果count<=m ,则意味着我们可以减少mid来增加子数组的数量,但是mid仍然是合格的。

So the pseudocode is:

因此,伪代码为:

while l < r:
mid = l + (r-l)//2
if count(mid) > m:
l = mid + 1
else:
r = mid
return l

如何选择中间,左和右 (How to pick the mid, l, and r)

选择中间(Pick the mid)

When picking the mid out of odd number of items, we can find the middle one; when the number of items is even, there are two ways to pick: the former one or the latter one.

当从奇数个项目中选择中间项目时,我们可以找到中间项目; 当项目数为偶数时,有两种选择方式:前一种或后一种。

Image for post
Pick the former one or the latter one out of an even number of items. 从偶数个项目中选择前一个或后一个。

Both of them works, but it should align with how we deal with l and r. When we select the former one using l+(r-l)//2, we want to make sure to avoid l = mid because that might lead to infinite loop. For example when there are two elements [0,1] and mid=0, then lbecomes mid and the iteration goes again and again.

它们都可以工作,但是应该与我们处理lr保持一致。 当我们使用l+(rl)//2选择前一个时,我们要确保避免l = mid因为这可能会导致无限循环。 例如,当有两个元素[0,1]mid=0l变为mid ,迭代一次又一次。

Similarly, when we select the latter one using r-(r-l)//2, we want to avoid r=mid.

同样,当我们使用r-(rl)//2选择后者时,我们要避免r=mid

给l和f赋值 (Assigning values to l and f)

So shall we assign values to l and r?

那么我们应该给lr赋值吗?

Image for post
How to assign values to l and r. 如何为l和r分配值。

It depends on the context!

这取决于上下文!

下界 (Lower bound)

For example, when the question asks for the lower bound, if mid works, then r should be mid not mid-1 because mid might be the answer! And when mid does not work, l should be mid+1 because we are sure the mid is not the answer and everything falls one mid‘s left won’t work either.

例如,当问题要求下限时,如果mid有效,则r应该是mid而不是mid-1因为mid可能是答案! 并且当mid不起作用时, l应该是mid+1因为我们确定mid不是答案,并且一切都落在mid的左边也不起作用。

Image for post
Assign l and r when asked for the lower bound. 当要求输入下限时分配l和r。

上限 (Upper bound)

Similarly, we can assign values to l and r as below.

类似地,我们可以如下为lr赋值。

Image for post
Assign l and r when asked for the upper bound. 当要求输入上限时,分配l和r。

In a word, the way we select mid and assign values to l and r is determined by which we are looking for: lower bound vs. upper bound.

简而言之,我们选择mid值并将值分配给lr方式取决于我们要寻找的内容:下限与上限。

Image for post
How to choose mid, l and r. 如何选择中,左和右。

Finally, we need to implement the count function and here’s the AC code.

最后,我们需要实现count功能,这是AC代码。

class Solution:
def splitArray(self, nums: List[int], m: int) -> int:
l,r,n = max(nums),sum(nums),len(nums)
def count(target):
ret = cur = 0
for num in nums:
if cur+num > target:
ret += 1
cur = num
else:
cur += num
return ret + 1

while l < r:
mid = l + (r-l)//2
if count(mid) > m:
l = mid + 1
else:
r = mid
return l

实践 (Practices)

You may find the following practices in the Leetcode:

您可能会在Leetcode中找到以下做法:

翻译自: https://medium.com/swlh/binary-search-find-upper-and-lower-bound-3f07867d81fb

控制上下限与规格上下限

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值