3ds max 卡顿优化
Binary Search is probably one of the most ‘interesting’ algorithm from our high school and sophomore college computer science course. But most of us have encountered binary search either in the context of searching in a sorted array or some tweaked versions of similar problem:
二进制搜索可能是我们高中和二年级大学计算机科学课程中最“有趣”的算法之一。 但是我们大多数人都遇到了二进制搜索,要么是在排序数组中搜索,要么是类似问题的一些调整版本:
- Find an element in a rotated sorted array (with and without duplicates allowed). 在旋转的排序数组中查找元素(允许和不允许重复)。
- Find an element in the 2D sorted array, only rows sorted, only columns sorted and both row and column sorted versions. 在2D排序数组中查找元素,仅对行进行排序,仅对列进行排序,并且对行和列进行排序。
While these problems are interesting enough to puzzle even the most well prepared interview candidates. But in this post I will go into a different direction with binary search. I will look at some more advanced problems that require binary search technique to solve them.
尽管这些问题很有趣,甚至使准备最充分的面试候选人也感到困惑。 但是在这篇文章中,我将对二进制搜索走一个不同的方向。 我将看一些需要二进制搜索技术才能解决的更高级的问题。
Finding solution to an optimization problem using Binary Search.
使用Binary Search查找优化问题的解决方案。
The idea is as follows:
这个想法如下:
We need to minimize or maximize a function F given some constraint C, where the range of values of F are integers in [N, M] (N ≤ M).
给定一些约束C,我们需要最小化或最大化函数F,其中F的值范围是[N,M]中的整数(N≤M)。
Let G be a function that maps a possible solution ‘f’ in F to an integer ‘c’ i.e. G[f] = c, then if G is monotonic i.e. increasing ‘f’ will either non-decrease ‘c’ or non-increase ‘c’ but never zig-zag, then we can use binary search to find the optimal ‘f’ which satisfies G[f] = C.
令G为将F中可能的解决方案'f'映射到整数'c'的函数,即G [f] = c,则如果G是单调的,即增加'f'将不减小'c'或不减小增加“ c”而不是“之字形”,那么我们可以使用二进制搜索找到满足G [f] = C的最优“ f”。
For e.g. start with f = (N+M)/2, now if G[f] = c < C and increasing ‘f’ also increases ‘c’, then we need to increase ‘f’ i.e. search the right half recursively. But if decreasing ‘f’ increases ‘c’, then we need to decrease ‘f’, i.e. search the left half recursively.
例如,从f =(N + M)/ 2开始,现在如果G [f] = c <C并且增加'f'也增加'c',则我们需要增加'f',即递归搜索右半部分。 但是,如果减小“ f”会增加“ c”,那么我们需要减小“ f”,即递归搜索左半部分。
Let’s look at 6 problems with varying levels of difficulty to understand this technique thoroughly. Later on I will talk about some pitfalls to look out for.
让我们看一下难度各不相同的6个问题,以全面了解该技术。 稍后,我将讨论一些需要注意的陷阱。
Problem 1:
问题一:
Koko loves to eat bananas. There are N
piles of bananas, the i
-th pile has piles[i]
bananas. The guards have gone and will come back in H
hours.
Koko喜欢吃香蕉。 有N
香蕉成堆时, i
个桩具有piles[i]
香蕉。 守卫走了,将在H
小时后回来。
Koko can decide her bananas-per-hour eating speed of K
. Each hour, she chooses some pile of bananas, and eats K bananas from that pile. If the pile has less than K
bananas, she eats all of them instead, and won't eat any more bananas during this hour.
Koko可以决定她的香蕉每小时进食速度K
每小时,她都会选择一堆香蕉,然后从那一堆中吃K根香蕉。 如果堆中的香蕉少于K
,她将全部吃掉,并且在此小时内不再吃香蕉。
Koko likes to eat slowly, but still wants to finish eating all the bananas before the guards come back.
Koko喜欢慢慢吃东西,但仍然想在警卫回来之前吃完所有香蕉。
Return the minimum integer K
such that she can eat all the bananas within H
hours.
返回最小整数K
,以便她可以在H
小时内吃掉所有香蕉。
Solution
解
In this problem, our constraint is the number of hours H to finish eating. The cost function F is the eating speed K. The range of K is [1, max(piles)] because Koko cannot eat more than max(piles) in an hour.
在这个问题上,我们的约束条件是完成饮食的小时数H。 成本函数F是进餐速度K。K的范围是[1,max(piles)],因为Koko在一个小时内不能吃得超过max(piles)。
We need to figure out the function G.
我们需要找出函数G。
In our problem, given that Koko eats ‘k’ bananas in an hour, how many hours he will take to finish ?
在我们的问题中,考虑到Koko在一个小时内吃完“ k”根香蕉,他需要花几个小时来完成?
Number of hours h = sum(ceiling(piles[i]/k)) over i in [0, len(piles)-1].
小时数h = [0,len(piles)-1]中i上的sum(ceiling(piles [i] / k))。
Thus G[k] = sum(ceiling(piles[i]/k)).
因此,G [k] = sum(ceiling(piles [i] / k))。
Note that increasing ‘k’ will decrease G[k] and vice versa. Thus for a choice of ‘k’ if G[k] < H, then we need to increase G[k] or decrease ‘k’ i.e. search in the left half recursively.
请注意,增加“ k”将减少G [k],反之亦然。 因此,如果G [k] <H,对于'k'的选择,则需要增加G [k]或减小'k',即递归搜索左半部分。
We can do binary search over ‘k’ from 1 to max(piles). Below is the python code for the following:
我们可以对'k'进行从1到max(piles)的二进制搜索。 以下是以下代码的python代码:
def g(piles, k):
s = 0
for i in range(len(piles)):
s += int(math.ceil(float(piles[i])/k))
return s
def minEatingSpeed(piles, H):
left, right = 1, max(piles)
p = -1
while left <= right:
k = int((left + right)/2)
if g(piles, k) <= H:
p = k
right = k-1
else:
left = k+1
return p
Time complexity of the approach is O(N*log(max(piles)). Because for each ‘k’ we need to scan the entire ‘piles’ array.
该方法的时间复杂度为O(N * log(max(piles))。因为对于每个'k',我们需要扫描整个'piles'数组。
Note that if G was not monotonic, then we cannot have done binary search over ‘k’ and in that case we would have iterated over all possible values of ‘k’. In that case time complexity would have been O(N*max(piles)).
注意,如果G不是单调的,那么我们不能对'k'进行二进制搜索,在这种情况下,我们将对'k'的所有可能值进行迭代。 在那种情况下,时间复杂度将是O(N * max(piles))。
Problem 2:
问题2:
Given an integer array ‘wood’ representing the length of n pieces of wood and an integer K. It is required to cut these pieces of wood such that more or equal to K pieces of the same length length are cut. What is the longest length you can get ?
给定一个表示n块木头的长度的整数数组'wood'和一个整数K。需要切割这些木头,以便切割更多或等于K个相同长度长度的木头。 您可以获得的最长长度是多少?
Solution
解
The problem is similar to Problem 1.
问题类似于问题1。
Our function F is the length of the longest wood. Our constraint is the final number of pieces K. As before the range of F is [1, max(wood)] because we cannot have a piece which is longer than the largest piece of wood.
我们的函数F是最长木材的长度。 我们的约束条件是最终的碎片数K。与之前一样,F的范围是[1,max(wood)],因为我们的碎片不能长于最大的木板。
For a given ‘f’ i.e. longest piece of wood, the total number of pieces ‘k’ of length ‘f’ is:
对于给定的“ f”,即最长的一块木头,长度为“ f”的一块“ k”的总数为:
G[f] = k = sum(int(wood[i]/f)) because if wood[i] = 300 and ‘f’=120, then we can cut wood[i] into 2 pieces of length 120 and one piece of length 60.
G [f] = k = sum(int(wood [i] / f)),因为如果wood [i] = 300且'f'= 120,则我们可以将wood [i]切成2个长度为120的片段长度为60。
Also increasing ‘f’ decreases ‘k’ and vice-versa. Thus we can do binary search over ‘f’ to find the optimum value of ‘f’.
同样,增加“ f”会减少“ k”,反之亦然。 因此,我们可以对“ f”进行二进制搜索以找到“ f”的最佳值。
def g(arr, f):
cnts = 0
for x in arr:
cnts += int(x/f)
return cnts
def cut_wood(arr, k):
if len(arr) == 0:
return 0
left, right = 1, max(arr)
last_true = 0
while left <= right:
mid = int((left + right)/2)
if g(arr, mid) >= k:
last_true = mid
left = mid+1
else:
right = mid-1
return last_true
Time complexity of the approach is O(N*log(max(wood)). Because for each ‘f’ we need to scan the entire ‘wood’ array.
该方法的时间复杂度为O(N * log(max(wood))。因为对于每个'f',我们需要扫描整个'wood'阵列。
Problem 3:
问题三:
A conveyor belt has packages that must be shipped from one port to another within D
days.
传送带上的包裹必须在D
天内从一个港口运到另一个港口。
The i
-th package on the conveyor belt has a weight of weights[i]
. Each day, we load the ship with packages on the conveyor belt (in the order given by weights
). We may not load more weight than the maximum weight capacity of the ship.
传送带上的第i
个包装的重量为weights[i]
。 每天,我们将包裹装载在船上的传送带上(按weights
给定的顺序)。 我们所装载的重量不得超过船舶的最大承重量。
Return the least weight capacity of the ship that will result in all the packages on the conveyor belt being shipped within D
days.
返回船舶的最小重量,这将导致在D
天之内运送完传送带上的所有包裹。
Solution
解
Our function F is the weight capacity of the ship and constraint is the number of days D.
我们的函数F是船舶的重量能力,约束条件是天数D。
The range of the function F is [max(weights), sum(weights)] because if the ship carries one package at a time then it must have capacity equal to the heaviest package. Also if the ship has capacity equal to the sum of the weights then it can take all packages at once.
函数F的范围是[max(weights),sum(weights)],因为如果船舶一次携带一个包裹,那么它的容量必须等于最重的包裹。 同样,如果船舶的载重量等于重量之和,那么它可以一次取走所有包裹。
For a given ‘f’ i.e. weight capacity of the ship, number of days required to ship can be found greedily as follows (the function G):
对于给定的“ f”,即船的重量,可以如下贪婪地找到需要运输的天数(函数G):
Starting from the 1st package, put these packages in the ship until the total weight of the packages do not exceed ‘f’. Repeat this for the remaining packages till all packages are shipped.
从第一个包裹开始,将这些包裹放入船中,直到包裹的总重量不超过“ f”。 对剩余的包装重复此操作,直到所有包装都寄出为止。
On increasing ‘f’ the number of days to ship will reduce because more weights can now be taken at once.
随着“ f”的增加,发货天数将减少,因为现在可以一次承担更多的重量。
def g(weights, k):
num_days = 0
curr_weight_sum = 0
for i in range(len(weights)):
if curr_weight_sum + weights[i] <= k:
curr_weight_sum += weights[i]
else:
num_days += 1
curr_weight_sum = weights[i]
num_days += 1
return num_days
def shipWithinDays(weights, D):
left, right = max(weights), sum(weights)
while left <= right:
mid = int((left+right)/2)
if g(weights, mid) <= D:
last_true = mid
right = mid-1
else:
left = mid+1
return last_true
Runtime complexity of the approach is O(N*log(sum(weights)-max(weights)).
该方法的运行时复杂度为O(N * log(sum(weights)-max(weights))。
Problem 4:
问题4:
On an N x N grid
, each square grid[i][j]
represents the elevation at that point (i,j)
.
在N x N grid
,每个正方形grid[i][j]
表示该点(i,j)
的高程。
Now rain starts to fall. At time t
, the depth of the water everywhere is t
. You can swim from a square to another 4-directionally adjacent square if and only if the elevation of both squares individually are at most t
. You can swim infinite distance in zero time. Of course, you must stay within the boundaries of the grid during your swim.
现在下雨了。 在时间t
处到处的水深为t
。 当且仅当两个正方形的高程最大为t
您才能从一个正方形游泳到另一个4向相邻的正方形。 您可以在零时间内游泳无限距离。 当然,游泳时必须保持在网格的边界内。
You start at the top left square (0, 0)
. What is the least time until you can reach the bottom right square (N-1, N-1)
?
您从左上角的正方形(0, 0)
。 到达右下角的正方形(N-1, N-1)
最少需要多少时间?
Solution
解
In this problem, our function F is the time when he wants to swim to (N-1, N-1) from (0, 0) and the constraint is that the probability that he can reach the end is 1.0
在这个问题中,我们的函数F是他要从(0,0)游向(N-1,N-1)的时间,并且约束条件是他可以到达终点的概率为1.0
The range of F is [min(grid), max(grid)] because if all the squares are at same elevation then he can swim at time ‘min(grid)’. Also after ‘max(grid)’ time all squares will be under water and thus can swim.
F的范围是[min(grid),max(grid)],因为如果所有正方形都在同一高度,则他可以在“ min(grid)”时间游泳。 同样,在“ max(grid)”时间过后,所有方块都将在水下,因此可以游泳。
For a given ‘f’ i.e. time at which he wants swim to end, the probability that he will reach (N-1, N-1) from (0, 0) is 1 if there is a path with all squares at elevation less than equal to ‘f’ else 0. Thus the function G is a DFS traversal that return True or False (corresponding to probability 1 or 0).
对于给定的“ f”,即他想要游泳结束的时间,如果存在一条路径,且所有正方形的仰角都小于,则他从(0,0)到达(N-1,N-1)的概率为1等于'f'否则为0。因此,函数G是返回True或False(对应于概率1或0)的DFS遍历。
Also note that when ‘f’ increases, there is more probability that he can swim at time ‘f’ because number of squares with elevation less than ‘f’ would be more. The function G varies with increasing ‘f’ as follows : [0 0 0 … 0 1 1 ..1] i.e. non-decreasing function of ‘f’.
还要注意,当“ f”增加时,他有更多机会在“ f”时间游泳,因为高程小于“ f”的正方形数量会更多。 函数G随着'f'的增加而变化,如下所示:[0 0 0…0 1 1 ..1],即'f'的不减少的函数。
def traverse(grid, curr_height, x, y, visited):
n = len(grid)
if (x, y) == (n-1, n-1):
return True
visited.add((x, y))
p = [[0,-1],[-1,0],[0,1],[1,0]]
for a, b in p:
if 0 <= x+a < n and 0 <= y+b < n and (x+a, y+b) not in visited and grid[x+a][y+b] <= curr_height:
if traverse(grid, curr_height, x+a, y+b, visited):
return True
return False
def g(grid, curr_height):
n = len(grid)
if grid[0][0] > curr_height or grid[n-1][n-1] > curr_height:
return False
return traverse(grid, curr_height, 0, 0, set())
def swimInWater(grid):
n = len(grid)
left, right = min([min(grid[i]) for i in range(n)]), max([max(grid[i]) for i in range(n)])
p = -1
while left <= right:
mid = int((left + right) / 2)
if g(grid, mid):
p = mid
right = mid - 1
else:
left = mid + 1
return p
Time complexity is O(N²*log(max(grid))).
时间复杂度为O(N²* log(max(grid)))。
Problem 5:
问题5:
Given an integer array X, return the k-th smallest distance among all the pairs. The distance of a pair (A, B) is defined as the absolute difference between A and B.
给定整数数组X,返回所有对中的第k个最小距离。 一对(A,B)的距离定义为A和B之间的绝对差。
Solution
解
The function F is the absolute difference between any pair (A, B) and the constraint is that there should be exactly k-1 distances smaller than the optimal value of F.
函数F是任何一对(A,B)之间的绝对差,并且约束条件是准确地存在k-1个距离,该距离小于F的最佳值。
If we sort the array X, then the range of the function can be defined as follows: [min(X[i]-X[i-1]), X[len(X)-1]-X[0]]
如果我们对数组X排序,则函数的范围可以定义如下:[min(X [i] -X [i-1]),X [len(X)-1] -X [0]]
i.e. the minimum absolute difference is the minimum of the absolute difference between all consecutive elements in sorted X. And the maximum difference the difference between the largest and the smallest element in X.
也就是说,最小绝对差是排序的X中所有连续元素之间的绝对差的最小值。最大差是X中最大和最小元素之间的差。
For a given ‘f’ i.e. an absolute difference value, we can find the number of differences less than equal to ‘f’ as follows:
对于给定的“ f”,即绝对差值,我们可以找到小于等于“ f”的差的数量,如下所示:
If the sorted X is as follows: [x0, x1, … xn-1], then for x0, find largest i such that (xi-x0) ≤ f. For all k, 0 < k ≤ i, (xk-x0) ≤ f. Thus the count of differences less than equal to f starting at index 0 is ‘i’.
如果排序的X如下:[x0,x1,…xn-1],则对于x0,找到最大的i,使得(xi-x0)≤f。 对于所有k,0 <k≤i,(xk-x0)≤f。 因此,从索引0开始小于等于f的差的计数为'i'。
Similarly for x1 find largest j, such that (xj-x1) ≤ f. Add up the number of distances for each index.
类似地,对于x1,找到最大j,使得(xj-x1)≤f。 累加每个索引的距离数。
This can be achieved in O(nlogn) using a binary search technique because X is sorted. But we can also use a trick to do it in O(n) by using a queue. Starting from index 0 keep adding elements into the queue until for some i > 0, (xi-x0) > f. Then remove all elements from the front of the queue for which (xi-xj) > f where j < i. Repeat this by adding the next elements into the queue.
由于X已排序,因此可以使用二进制搜索技术在O(nlogn)中实现。 但是我们也可以通过使用队列在O(n)中使用技巧。 从索引0开始,继续将元素添加到队列中,直到某些i> 0,(xi-x0)> f。 然后从队列的最前面删除所有元素(xi-xj)> f,其中j <i。 通过将下一个元素添加到队列中来重复此操作。
This ensures that at any moment in the queue, the difference in the value of the last element and the front element is ≤ f. The above function is the function G.
这样可以确保在队列中的任何时刻,最后一个元素和最前面的元素的值之差≤f。 上面的函数是函数G。
Also note that on increasing ‘f’, the number of differences ≤ f will also increase thus the function G is a monotonic increasing function. Thus we can easily apply binary search to find optimal ‘f’ such that if count is ≤ k, then increase ‘f’ else decrease ‘f’.
还应注意,在增加“ f”时,差值≤f的数目也会增加,因此函数G是单调递增函数。 因此,我们可以轻松地应用二进制搜索来找到最佳的“ f”,使得如果count≤k,则增加“ f”,否则减少“ f”。
Below is the Python code for the implementation.
以下是实现的Python代码。
def g(nums, k):
queue = collections.deque([[nums[0], 0]])
cnts, max_diff = 0, -float("Inf")
for i in range(1, len(nums)):
while len(queue) > 0 and nums[i]-queue[0][0] > k:
max_diff = max(max_diff, nums[i-1]-queue[0][0])
cnts += (i-1-queue[0][1])
queue.popleft()
queue.append([nums[i], i])
while len(queue) > 0:
max_diff = max(max_diff, nums[-1]-queue[0][0])
cnts += (len(nums)-1-queue[0][1])
queue.popleft()
return cnts, max_diff
def smallestDistancePair(nums, k):
nums = sorted(nums)
min_u = min([nums[i]-nums[i-1] for i in range(1, len(nums))])
left, right = min_u, nums[-1]-nums[0]
u = float("Inf")
while left <= right:
mid = int((left + right)/2)
p, x = g(nums, mid)
if p >= k:
u = x
right = mid-1
else:
left = mid+1
return u
Note that we return another value from the function ‘g’ which is the ‘cnt’-th difference where ‘cnt’ is the number of differences smaller than equals to f.
请注意,我们从函数“ g”返回另一个值,该值是第“ cnt”个差,其中“ cnt”是小于等于f的差的数量。
This is required as ‘f’ is not continuous i.e. there may be some value of f such that the number of differences less than equals to f would be k but there are no pair (A, B) for which |A-B|=f.
这是必需的,因为“ f”不是连续的,即可能存在f的某个值,使得小于等于f的差的个数为k,但不存在| AB | = f的对(A,B)。
Time complexity is O(N*log(max(nums))).
时间复杂度为O(N * log(max(nums)))。
Problem 6:
问题6:
Given an array A of N integers. You are also given two integers S and M. Each time you can pick a subarray of size S and increment the values in the subarray by 1. Repeat this at-most M times.
给定一个由N个整数组成的数组A。 还为您提供了两个整数S和M。每次选择大小为S的子数组并将该子数组中的值增加1。最多重复M次。
Find the maximum value of minimum value in array A.
在数组A中找到最小值的最大值。
Solution
解
The function F in this example is the minimum value in A after the increment operations. We need to maximize the cost function. The constraint in this example is the number of operations M.
在此示例中,函数F是增量操作后A中的最小值。 我们需要最大化成本函数。 此示例中的约束是操作数M。
The range of the function F is [min(A), min(A)+M], because the after M operations, the minimum value cannot be less than the current minimum and cannot be more than the current minimum + M because we can do at-most M operations.
函数F的范围是[min(A),min(A)+ M],因为经过M次运算,最小值不能小于当前最小值,也不能大于当前最小值+ M,因为我们可以最多执行M个操作。
For a given minimum value ‘f’, the function G needs to return the minimum number of operations required. Note that if the minimum value ‘f’ is higher then the number of operations required is also high i.e. number of operations is a non-decreasing function with increasing ‘f’.
对于给定的最小值“ f”,函数G需要返回所需的最小操作数。 注意,如果最小值“ f”较高,则所需的操作数也将较高,即,操作数是随着“ f”增加而不变的函数。
To compute the number of operations required to obtain ‘f’, we can use the following algorithm:
要计算获得“ f”所需的操作数,我们可以使用以下算法:
We need to increment all elements A[i] < f to be equal to f.
我们需要将所有元素A [i] <f递增为等于f。
For this maintain a queue of size S. When an element is inserted into the queue, if the value is less than h = f-(A[i]+sum_of_queue), then make ‘h’ operations to increment the value A[i] to f and accordingly add ‘h’ to queue and ‘sum_of_queue’. When size of queue exceeds S, remove the first element from queue and decrease ‘sum_of_queue’.
为此,维持一个大小为S的队列。将元素插入队列时,如果该值小于h = f-(A [i] + sum_of_queue),则执行'h'操作以增加值A [i ]到f,并相应地将'h'添加到队列和'sum_of_queue'。 当队列的大小超过S时,从队列中删除第一个元素并减少'sum_of_queue'。
Below is the Python solution:
以下是Python解决方案:
def num_steps(arr, s, k):
queue = collections.deque([])
queue_sum, n_steps = 0, 0
for i in range(len(arr)):
while len(queue) > 0 and i-queue[0][0]+1 > s:
j, x = queue.popleft()
queue_sum -= x
if arr[i] + queue_sum < k:
h = k - (arr[i] + queue_sum)
n_steps += h
queue.append([i, h])
queue_sum += h
return n_steps
def min_value(arr, s, m):
if s >= len(arr):
return min(arr)+m
k = min(arr)
left, right = k, k+m
p = -1
while left <= right:
mid = int((left+right)/2)
q = num_steps(arr, s, mid)
if q <= m:
p = mid
left = mid+1
else:
right = mid-1
return p
Time complexity is O(N*logM)
时间复杂度为O(N * logM)
The Pitfall
陷阱
Although it is very tempting to use the Binary Search technique for such optimization problems but this tool is like a ‘hammer in the toolbox’. There are scenarios where instead of O(nlogn) binary search solution, we can solve a problem in O(n) time complexity where the problem characteristics are same as the ones above.
尽管使用二进制搜索技术解决此类优化问题非常诱人,但该工具就像“工具箱中的锤子”。 在某些情况下,可以使用O(n)时间复杂度代替问题的特征与上述特征相同的方法,而不是使用O(nlogn)二进制搜索解决方案。
Let’s look at a problem to understand where Binary Search solution is not the most ‘efficient’.
让我们看一个问题,以了解Binary Search解决方案不是最“高效”的地方。
Problem 7:
问题7:
Given an array of N positive integers and a positive integer s, find the minimal length of a contiguous subarray of which the sum ≥ s. If there isn’t one, return 0 instead.
给定一个由N个正整数和一个正整数s组成的数组,请找到总和≥s的连续子数组的最小长度。 如果没有,则返回0。
Solution
解
Here the function F is the length of a subarray. The constraint is that the sum of a subarray ≥ s. Given a length of subarray ‘f’, the function G returns 1 if there is a subarray of length ‘f’ with sum ≥ s else return 0.
在这里,函数F是子数组的长度。 约束条件是子数组的总和≥s。 给定子数组'f'的长度,如果存在长度为'f'的子数组且sum≥s,则函数G返回1.否则返回0。
Since the array consists of only positive integers, increasing the length ‘f’ increases the probability that sum ≥ s. Thus we are tempted to use binary search over the length of subarray. Which will work just fine !!!
由于数组仅由正整数组成,因此增加长度'f'会增加sum≥s的可能性。 因此,我们很想在子数组的长度上使用二进制搜索。 哪个会很好!
def g(arr, k, s):
queue = collections.deque([])
queue_sum = 0
for i in range(len(arr)):
if len(queue) == k:
if queue_sum >= s:
return True
x = queue.popleft()
queue_sum -= x
queue.append(arr[i])
queue_sum += arr[i]
if len(queue) == k:
if queue_sum >= s:
return True
return False
def min_subarray(arr, s):
left, right = 1, len(arr)
p = 0
while left <= right:
mid = int((left + right)/2)
if g(arr, mid, s):
p = mid
right = mid-1
else:
left = mid+1
return p
The time complexity of the above approach is O(NlogN).
上述方法的时间复杂度为O(NlogN)。
But we can solve the same problem using a O(N) approach using only a Queue data structure.
但是我们可以使用仅使用队列数据结构的O(N)方法来解决相同的问题。
def minSubArrayLen(s, nums):
if len(nums) == 0:
return 0
queue = collections.deque([])
queue_sum = 0
min_length = float("Inf")
for i in range(len(nums)-1, -1, -1):
while len(queue) > 0 and queue_sum >= s:
min_length = min(min_length, len(queue))
queue_sum -= queue.popleft()
queue.append(nums[i])
queue_sum += nums[i]
while len(queue) > 0 and queue_sum >= s:
min_length = min(min_length, len(queue))
queue_sum -= queue.popleft()
return min_length if min_length != float("Inf") else 0
The idea is simple: In the queue, if the queue sum is ≥ s, then start removing elements from the beginning of the queue until queue sum < s.
这个想法很简单:在队列中,如果队列总和≥s,则从队列的开头开始删除元素,直到队列总和<s。
In interviews it is perfectly fine to come up with a O(nlogn) binary search solution in the first attempt instead of an ‘inefficient’ O(n²) approach. One can always improve upon the O(nlogn) solution to O(n) from there on.
在采访中,第一次尝试使用O(nlogn)二进制搜索解决方案而不是“低效” O(n²)方法是完全可以的。 从那时起,人们总是可以将O(nlogn)解决方案改进为O(n)。
In a separate post we will discuss another variation of problem solving using Binary Search. Gonna be interesting !!!
在另一篇文章中,我们将讨论使用Binary Search解决问题的另一种形式。 会很有趣!
翻译自: https://medium.com/swlh/problems-with-advanced-ds-binary-search-optimization-56efedb274d5
3ds max 卡顿优化