查找不包括某些对的连续子阵列的数量

时间:2015-08-11 17:37:54

标签: algorithm math combinations combinatorics

存在多少个连续的数组子阵列,使得它们不包含数组的某些位置对?例如。如果array = {11,22,33,45}并且如果我们不想包括说位置编号(1,3)和(2,4)那么存在的连续子阵列的数量是7,如下{{11 },{22},{33},{44},{11,22},{22,33},{33,45}}

我尝试解决问题:

如果存在两对{...,a1,...,a2,..,b1,..,b2},其中n是元素的数量,(...)表示有元素在这些职位之间。

第一种情况:我们不能包括{a1,b1}和{a2,b2}然后我们必须计算可能的组合数,即n *(n + 1)/ 2 - 否。可能的组合包括{a2,b1},涵盖所有可能的

案例2.如果我们不能包含对{a1,b2}和{a2,b1},那么我们只需减去包含{a2,b1}的可能性的数量,其中包含所有可能的案例。

第3种情况:如果我们不能包含对{a1,a2}和{b1,b2}那么我们必须单独减去可能的子阵列,包括这些位置

我面临的问题是,即使在制定案例后,我也无法推导出一个公式,并将这些案例扩展到2对以上,以计算可能的解决方案的数量。所以,我需要帮助。

来源:这是一个面试问题,问我的朋友,他无法回答。

1 个答案:

答案 0 :(得分:0)

好的,让我们再看一下阵列{11,22,33,44}。

让我们假设您正在尝试查找以11开头的所有子阵列(index = 1)。现在你只需要查看索引< = a和b是最小的限制(a,b),因为如果你有例如(2,3)这自动暗示(1,4)或(2,4)。

要查找最小b,请使用以下代码(我使用C#):

public static int  findRestrictingIndex(int currentIndex, List<Tuple<int, int>> restrictions)
    {
        int result = int.MaxValue;
        foreach (var pair in restrictions)
        {
            if (currentIndex <= pair.Item1)
            {
                if (pair.Item2 < result)
                    result = pair.Item2;
            }
        }
        return result;
    }

如果您运行此代码,您将收到3(来自(1,3))的结果。以11开头的数组的数量则为3-1 = 2,因为您可以将数字添加到11直到排除索引3。

为每个索引执行此操作,您将完成:

int arrayLength = 4;

//excluded positions, zero-based
List<Tuple<int, int>> restrictions = new List<Tuple<int, int>>();
restrictions.Add(new Tuple<int, int>(0, 2));
restrictions.Add(new Tuple<int, int>(1, 3));
restrictions.Add(new Tuple<int, int>(4, 4));    //dummy element when there is no restriction

int numOfSubarrays = 0;
for (int currentIndex = 0; currentIndex < arrayLength; currentIndex++)
{
    numOfSubarrays += findRestrictingIndex(currentIndex, restrictions) - currentIndex;
}
Console.WriteLine(numOfSubarrays);