这可以用线性时间复杂度解决吗?

Posted

技术标签:

【中文标题】这可以用线性时间复杂度解决吗?【英文标题】:Can this be solved in linear time complexity? 【发布时间】:2015-09-10 22:49:48 【问题描述】:

给定一个由 N 个整数组成的数组(元素为正数或 -1),以及另一个整数 M。 对于每个 1 ,我们可以跳转到数组的 i + 1, i + 2, .. i + M 索引。从索引 1 开始,有一个线性 O(N) 算法,可以找出最小成本以及到达 Nth 索引的路径。其中成本是从 1 到 N 的路径中所有元素的总和。我有一个复杂度为 O(N*M) 的动态规划解决方案。 注意:如果 A[i] 为 -1,则表示我们无法登陆第 ith 索引。

【问题讨论】:

非负值是走这条路的成本吗?否则,这是一个微不足道的贪心算法:尽可能跳(向后搜索来自A[i+M] 的非负条目),直到i+M >= N 如果数组值是成本,那么你有一个图问题,有向无环图。每个节点A[i] 连接到所有具有非负索引的节点A[i+1 .. i+M]。您存储图形的方式可能对寻路算法有利也可能不利,但转换为另一种表示形式可以在线性时间内完成。 我认为 O(NM) 复杂度的动态规划解决方案。即使你用一个图,这个图的节点也是O(mn)... @kaitian:有 N 个节点,但有 O(N*M) 边。问题是是否有办法利用冗余:进入A[i] 的所有边具有相同的成本。显然,您可以非常快速地找到 a 路径,甚至可以对其进行一些细化以找到局部最小值。 (启发式取决于预期的成本分布。例如,找到A[i+M-16 .. i+M] 的最小值。) 请解释什么是成本属性。显然不允许使用负值。对吗? 【参考方案1】:

如果我正确理解您的问题,A* 可能会为您提供最佳运行时。对于每个 ii+1 到 i+M 将是子节点,而 h 将是从 iN 的成本,假设每个后续节点的成本为 1(例如,如果 N=11 M=4 然后 h=3 for i=2,因为这是到达最终索引所需的最少跳转次数) .

【讨论】:

【参考方案2】:

新方法

Assumption:该图不是加权图。

这种解释方法可以在线性时间内解决问题。 所以,算法如下。

int A[N];         // It contains the initial values
int result[N];    // Initialise all with positive infinty or INT_MAX in C
bool visited[N];  // Initially, all initialise with '0' means none of the index is visited

int current_index = 1
cost = 0
result[current_index] = cost
visited[current_index] = true

while(current_index less than N) 
    cost = cost + 1    // Increase the value of the cost by 1 in each level
    
    int last_index = -1 /* It plays the important role, it actually saves the last index 
                          which can be reached form the currnet index, it is initialised 
                          with -1, means it is not pointing to any valid index*/
    for(i in 1 to M) 
        temp_index = current_index + i;
        if(temp_index <= N   AND  visited[temp_index] == false   AND  A[temp_index] != -1) 
            result[temp_index] = cost
            visited[temp_index] = true
            last_index = temp_index
        
    
    
    if(last_index == -1) 
        print "Not possible to reach"
        break
     else 
        current_index = last_index
    


// Finally print the value of A[N]
print A[N]

做,当你完成这个方法时告诉我。

================================================ ============================

以前的方法

虽然,这种解释方法也是线性的。但相信我,它会比你的动态方法更有效。因为在您的方法中它总是需要 O(N.M) 时间,但在这里它可以减少到 O(n.M),其中 n 是数字数组中具有 no -1 值的元素。

Assumption: 在这里,我认为 A[1] 和 A[N] 的值不是-1。而且,数组中连续的-1 多于M-1 个。否则,我们无法完成这项工作。

现在,进行如下描述的BFS

int A[N];         // It contains the initial values
int result[N];    // Initialise all with positive infinty or INT_MAX in C
bool visited[N];  // Initially, all initialise with '0' means none of the index is visited
queue Q;          // create a queue 

index = 1
cost = 0
push index in rear of Q.
result[index] = cost
visited[index] = true

while(Q is not empty) 
    index = pop the value from the front of the Q.
    cost = cost + 1
    
    for(i in 1 to M) 
        temp_index = index + i;
        if(temp_index <= N   AND  visited[temp_index] == false   AND  A[temp_index] != -1) 
            push temp_index in rear of Q.
            result[temp_index] = cost
            visited[temp_index] = true
        
    


// Finally print the value of A[N]
print A[N]

注意:最坏情况下的时间复杂度与 DP 相同。 对算法有任何疑问,欢迎 cmets。而且,如果有人比我有更好的方法,请分享。 毕竟,我们是来学习的。

【讨论】:

是的,bfs也可以用来解决这个问题,但是最坏情况的复杂度仍然没有提高。 @PrakharAgarwal 这个问题在哪个网站上,你能给我它的链接吗,因为我有一个 linear 方法,但不确定,它是否正确.所以,首先让我为你检查一下,然后我会在完成后分享。 :) 它被用于校内编码竞赛。所以,很抱歉,但无法从大学网络之外访问它。 好的。告诉我应该在这里自己给出解决方案还是为其创建新的答案部分。 您可以编辑您的原始答案以添加新的解决方案,以便在正确的情况下对其进行投票。

以上是关于这可以用线性时间复杂度解决吗?的主要内容,如果未能解决你的问题,请参考以下文章

sort是线性表里的函数吗

大厂算法系列学数据结构与算法有用吗?时间与空间复杂度的定义与计算

真正复杂查询的 ORM 解决方案

桶排序原理及实现

树遍历的时间复杂度是多少?

为啥这个循环的时间复杂度是非线性的?