简体   繁体   English

严格递增子序列的最小数量

[英]Minimum number of strictly increasing subsequences

Problem Statement问题陈述

Adrian is a runner and every morning he goes for a run with his friends.阿德里安是一名跑步者,每天早上他都会和朋友一起去跑步。 Every morning, their coach gives them a list of checkpoints from left to right to cover.每天早上,他们的教练都会给他们一份从左到右到覆盖的检查站清单。 Each checkpoint has a special value.每个检查点都有一个特殊的值。 Now, the coach has a rule such that a runner will only go to checkpoints whose value is strictly higher than the previous checkpoints.现在,教练有一个规则,即跑步者只会去值严格高于之前检查点的检查点。 Also, all runners are supposed to move strictly towards the right.此外,所有跑步者都应该严格向右移动。 You need to find out the minimum number of runners it would take to cover all the checkpoints.您需要找出覆盖所有检查点所需的最少跑步者人数。

The input is taken in the form of an array which denotes the values of checkpoints from left to right.输入采用数组的形式,从左到右表示检查点的值。

Sample Input样本输入

[12, 15, 18, 17, 20, 25, 27, 19, 20, 21]

Sample Output样本输出

2

Explanation of the Sample Case:案例说明:

First runner will cover [12, 15, 18, 19, 20, 21] and the second runner will cover [17, 25, 27].第一名将覆盖 [12, 15, 18, 19, 20, 21],第二名将覆盖 [17, 25, 27]。

My code我的代码

My recursive algorithm gives the correct output but it is not efficient enough.我的递归算法给出了正确的输出,但效率不够高。

visited = [0] * len(A)
def ans(A, visited):
    n = len(A)
    if visited.count(0) == 0:
        return 0
    num = 0
    ind = visited.index(0)
    visited[ind] = 1
    min_num = A[ind]
    for i in range(ind, n):
        if A[i] > min_num and visited[i] == 0:
            visited[i] = 1
            min_num = A[i]
    return 1 + ans(A, visited)  

Question

What's the way this problem could be solved more efficiently?有什么方法可以更有效地解决这个问题? My code was giving TLE on some test cases.我的代码在一些测试用例上给出了 TLE。 I couldn't figure out how to make it work.我不知道如何让它工作。

My code was giving the correct output.我的代码给出了正确的输出。 It is just not efficient enough.它只是不够有效。

Your algorithm has a time complexity of O(n²) .您的算法的时间复杂度为O(n²)

You can use the following O(nlogn) algorithm:您可以使用以下O(nlogn)算法:

Create an empty list, which will get one value per needed runner (so far).创建一个空列表,它将为每个需要的跑步者获得一个值(到目前为止)。 For each runner you will store the maximum value that the corresponding runner will visit (so far), and the values (once they get in there) will be ordered in descending order (invariant).对于每个跑步者,您将存储相应跑步者将访问的最大值(到目前为止),并且这些值(一旦他们进入那里)将按降序排列(不变)。

Go through the input once.通过输入一次。 For each visited value v , perform a binary search in the above mentioned list in order to find the greatest value w that is less than it.对于每个访问过的值v ,在上面提到的列表中执行二分搜索以找到小于它的最大值w If found, overwrite that w with v (ie the corresponding runner will visit it).如果找到,用v覆盖那个w (即相应的跑步者将访问它)。 If not found, then append v to that list: this means an additional runner is needed.如果未找到,则将v附加到该列表中:这意味着需要一个额外的跑步者。 Of course, that will be the case when processing the first input value.当然,处理第一个输入值时就是这种情况。

At the end of this process, the length of the new list represents the answer (the minimum number of runners needed).在此过程结束时,新列表的长度代表答案(所需的最小跑步者数量)。

Implementation执行

For the binary search I'll use bisect , but you can of course implement your own.对于二分搜索,我将使用bisect ,但您当然可以实现自己的。

As bisect only works on lists that are in ascending order, I will visit the elements from A in reverse order, and update the runner's information to be the minimum value so far -- as we are working in the opposite direction:由于bisect仅适用于按升序排列的列表,因此我将以相反的顺序访问A中的元素,并将跑步者的信息更新为迄今为止的最小值——因为我们正朝着相反的方向工作:

def ans(A):
    runners = []
    for val in reversed(A):
        i = bisect.bisect_left(runners, val + 1)
        if i >= len(runners):
            runners.append(val)
        else:
            runners[i] = val
    return len(runners)

Note: val + 1 is needed to deal correctly with equal values (I assume integers).注意:需要val + 1才能正确处理相等的值(我假设是整数)。 In the case there is a duplicate value, this means the same runner cannot visit it, so we should look for a runner with at least a value of val + 1 (again: we are working backwards here).在有重复值的情况下,这意味着同一个 runner 不能访问它,所以我们应该寻找一个值至少为val + 1的 runner(再次:我们在这里倒退)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM