如何找到满足特定属性的各种长度的连续序列的数量

How can I find number of consecutive sequences of various lengths satisfy a particular property?

本文关键字:连续 何找 满足 属性      更新时间:2023-10-16

我得到一个数组 A[],其中包含 N 个正整数元素.我必须找到满足特定属性的长度为 1,2,3,..,N 的序列的数量?我已经构建了一个具有 O(nlogn) 复杂性的区间树。现在我想计算满足某个属性的序列数量?

问题所需的所有属性都与序列的总和有关

请注意,数组将有 N*(N+1)/2 个序列。如何在 O(nlogn) 或 O(n) 中迭代所有这些?

如果我们让 k 成为从 0 到 N(元素)的移动索引,我们将运行一个算法,该算法本质上是寻找满足条件的 MIN R(假设 I),那么 L = k 的所有其他子集也满足 R>= I(这是您的短路)。 找到 I 后,只需返回 (L=k, R>=I) 的输出。 当然,这假设集合中的所有数字都是>= 0。

要找到 I,对于每个 k,从元素 k + (N-k)/2 开始。 确定 (L=k, R=k+(N-k)/2) 中定义的子集是否满足您的条件。 如果是这样,则递减 R 直到您的条件不满足,那么 R=1 是您的 MIN(您可以选择随时打印这些结果,但在这些情况下,它们的结果基本上是向后打印的)。 如果 (L=k, R=k+(N-k)/2) 不能满足你的条件,那么递增 R 直到它满足,这将成为你 L=k 的最小值。 这会将每个 L=k 的搜索空间降低 2 倍。 当 k 增加并接近 N 时,您的搜索空间会不断减小。

// This declaration wont work unless N is either a constant or MACRO defined above
unsigned int myVals[N];
unsigned int Ndiv2 = N / 2;
unsigned int R;
for(unsigned int k; k < N; k++){
    if(TRUE == TESTVALS(myVals, k, Ndiv2)){ // It Passes
        for(I = NDiv2; I>=k; I--){
            if(FALSE == TESTVALS(myVals, k, I)){
                I++;
                break;
            } 
        }
    }else{                                  // It Didnt Pass
        for(I = NDiv2; I>=k; I++){
            if(TRUE == TESTVALS(myVals, k, I)){
                break;
            } 
        }
    }
    // PRINT ALL PAIRS from L=k, from R=I to R=N-1

    if((k & 0x00000001) == 0) Ndiv2++;
} // END --> for(unsigned int k; k < N; k++)

上述算法的复杂度为 O(N^2)。 这是因为对于 N(即 N 次迭代/测试)中的每个 k,需要测试的每个值都不大于 N/2。 大O符号不关心N/2,也不关心真正的N随着k的增长而变小的事实,它只关心总大小。 因此,它会说每 N 个值的 N 个测试,因此 O(N^2)

有一种替代方法会更快。 这种方法是,每当您希望在辅助(内部)循环内移动时,都可以使用距离算法执行移动。 这将使您进入O(nlogn)步骤集。 对于 N 中的每个 k(都必须进行测试),运行此半距离方法以在 logN 时间内找到您的最小 R 值。 例如,假设您有一个 1000 个元素的数组。 当 k = 0 时,我们基本上开始在索引 500 处搜索 MIN R。 如果测试通过,我们测试 250,而不是从 500 线性向下移动到 0。 假设 k = 0 的实际最小 R 是 300。 然后,查找 MIN R 的测试将如下所示:

R=500R=250R=375R=312R=280R=296R=304R=300

虽然这过于简化,但您很可能必须进行优化,并测试 301 以及 299 以确保您处于最佳状态。 另一个不是在除以 2 时要小心,当您必须连续多次朝同一方向移动时。

@user1907531:首先,如果你正在参加一个在国家层面如此重要的在线比赛,你应该避免做这种廉价的技巧和方法来领先于其他值得的人。其次,像你这样的作弊者总是作弊者,但所有这些都阻碍了那些提出问题的人和与你不同的竞争对手的辛勤工作。第三,如果@trumetlicks问你为什么不把问题标记为家庭作业,你在那里说另一个谎言。最后,我不知道怎么会有这么多人在不知道这个问题的来源/网站/来源的情况下回答这个作弊者提出的这个问题。这肯定不能由任何印度学校的老师做家庭作业。告诉大家,这个作弊者在比赛结束前 6 小时问了你在印度举行的大学比赛的完整解决方案,他肯定得到了很多直接帮助,最重要的是邀请了 100 人从这里给出的答案中作弊。所以,祝所有这些作弊者好运.