Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 给定序列中所有递增子序列的数目?_Algorithm - Fatal编程技术网

Algorithm 给定序列中所有递增子序列的数目?

Algorithm 给定序列中所有递增子序列的数目?,algorithm,Algorithm,你可能听说过一个众所周知的问题,那就是如何找到正确的答案。优化算法具有O(n*log(n))复杂度 我在考虑寻找给定序列中所有递增子序列的问题。我找到了一个我们需要解决的问题的解决方案,它具有O(n*k*log(n))复杂性(其中n是序列的长度) 当然,这个算法可以用于我的问题,但我想解决方案有O(n*k*log(n)*n)=O(n^2*k*log(n))复杂性。我认为,一定有更好(我是说更快)的解决方案,但我还不知道 如果您知道如何解决在给定序列中以最佳时间/复杂度查找所有递增子序列的问题(在

你可能听说过一个众所周知的问题,那就是如何找到正确的答案。优化算法具有
O(n*log(n))
复杂度

我在考虑寻找给定序列中所有递增子序列的问题。我找到了一个我们需要解决的问题的解决方案,它具有
O(n*k*log(n))
复杂性(其中n是序列的长度)

当然,这个算法可以用于我的问题,但我想解决方案有
O(n*k*log(n)*n)=O(n^2*k*log(n))
复杂性。我认为,一定有更好(我是说更快)的解决方案,但我还不知道

如果您知道如何解决在给定序列中以最佳时间/复杂度查找所有递增子序列的问题(在本例中,最佳=优于
O(n^2*k*log(n))
,请告诉我


最后:这个问题不是家庭作业。在我的讲座中提到了一个最长递增子序列的问题,我已经开始思考给定序列中所有递增子序列的一般概念。

我不知道这是否是最优的-可能不是,但这里有一个
O(n^2)
中的DP解

dp[i]=以i作为最后一个元素的递增子序列的数目

for i = 1 to n do
    dp[i] = 1
    for j = 1 to i - 1 do
        if input[j] < input[i] then
            dp[i] = dp[i] + dp[j] // we can just append input[i] to every subsequence ending with j
对于i=1到n do
dp[i]=1
对于j=1到i-1do
如果输入[j]<输入[i],则
dp[i]=dp[i]+dp[j]//我们可以将输入[i]附加到以j结尾的每个子序列中

然后,只需将
dp

中的所有条目相加,就可以计算出O(n logn)时间内递增子序列的数量,如下所示

回想一下最长递增子序列长度的算法:

对于每个元素,计算先前元素中的前置元素,并向该长度添加一个

如果您使用诸如平衡二叉搜索树(BST)之类的数据结构(或更高级的整数范恩德-博阿斯树)计算前驱体,则该算法在O(n^2)时间内运行,在O(n log n)时间内运行(或者更好,在整数的情况下)

要修改此算法以计算序列数,请将结束于该元素的序列数存储在每个节点的BST中。在处理列表中的下一个元素时,只需搜索前置元素,计算以小于当前正在处理的元素结尾的序列数(以O(logn)时间为单位),并将结果与当前元素一起存储在BST中。最后,对树中每个元素的结果求和以获得结果

需要注意的是,递增序列的数量可能非常大,因此算术运算不再需要每次运算O(1)个时间。这需要加以考虑

伪代码:

ret = 0
T = empty_augmented_bst() // with an integer field in addition to the key
for x int X:

  // sum of auxiliary fields of keys less than x
  // computed in O(log n) time using augmented BSTs
  count = 1 + T.sum_less(x)

  T.insert(x, 1 + count) // sets x's auxiliary field to 1 + count
  ret += count // keep track of return value

return ret

我假设输入A[0..(n-1)]由{0,1,…,n-1}中的所有整数组成,而不丧失泛化性

设DP[i]=以A[i]结尾的递增子序列的数目

我们有一个循环:

为了计算DP[i],我们只需要计算所有j的DP[j],其中A[j]A[i]

问题归结为计算DP[0]到DP[i-1]的和。假设我们已经计算了DP[0]到DP[i-1],我们可以使用芬威克树计算O(logn)中的DP[i]


最后的答案是DP[0]+DP[1]+。。。DP[n-1]。该算法在O(n log n)中运行。例如,Java版本:

    int[] A = {1, 2, 0, 0, 0, 4};
    int[] dp = new int[A.length];

    for (int i = 0; i < A.length; i++) {
        dp[i] = 1;

        for (int j = 0; j <= i - 1; j++) {
            if (A[j] < A[i]) {
                dp[i] = dp[i] + dp[j];
            }
        }
    }
int[]A={1,2,0,0,0,4};
int[]dp=新的int[A.长度];
for(int i=0;i
向量值
,一个n长度数组,是要搜索递增子序列的数组

vector<int> temp(n); // Array for sorting
map<int, int> mapIndex; // This will translate from the value in index to the 1-based count of values less than it

partial_sort_copy(values.cbegin(), values.cend(), temp.begin(), temp.end());

for(auto i = 0; i < n; ++i){
    mapIndex.insert(make_pair(temp[i], i + 1)); // insert will only allow each number to be added to the map the first time
}
值的所有n个元素
放入
二进制索引树
的所有k维后。收集到
结果
中的
s表示长度k的递增子序列的总数

用于获得此结果的二元索引树函数有:

void update(int rank, int increment, vector<int>& binaryIndexTree)
{
    while (rank < binaryIndexTree.size()) { // Increment the current rank and all higher ranks
        binaryIndexTree[rank - 1] += increment;
        rank += (rank & -rank);
    }
}

int getValue(int rank, const vector<int>& binaryIndexTree)
{
    auto result = 0;
    while (rank > 0) { // Search the current rank and all lower ranks
        result += binaryIndexTree[rank - 1]; // Sum any value found into result
        rank -= (rank & -rank);
    }
    return result;
}
void更新(整数秩、整数增量、向量和二进制索引树)
{
而(rank0){//搜索当前秩和所有较低的秩
result+=binaryIndexTree[rank-1];//对结果中找到的任何值求和
秩-=(秩和秩);
}
返回结果;
}
二叉索引树显然是O(nklogn),但正是顺序填充的能力创造了将其用于解决方案的可能性

mapIndex
values
中的每个数字创建一个秩,这样
values
中的最小数字的秩为1。(例如,如果
values
是“2,3,4,3,4,1”,那么
mapIndex
将包含:“{1,1},{2,2},{3,3},{4,5}”。“4”的秩5是因为有2个“3”值中的s

binaryIndexTree
有k个不同的树,级别x表示可以由长度x组成的递增子字符串的总数。
value
中的任何数字都可以创建长度为1的子字符串,因此每个元素将其秩和其上的所有秩递增1。
在更高的级别,子字符串的增加取决于已经存在一个长度更短、级别更低的可用子字符串

由于元素是根据其在
值中的顺序插入到二叉索引树中的,因此
void update(int rank, int increment, vector<int>& binaryIndexTree)
{
    while (rank < binaryIndexTree.size()) { // Increment the current rank and all higher ranks
        binaryIndexTree[rank - 1] += increment;
        rank += (rank & -rank);
    }
}

int getValue(int rank, const vector<int>& binaryIndexTree)
{
    auto result = 0;
    while (rank > 0) { // Search the current rank and all lower ranks
        result += binaryIndexTree[rank - 1]; // Sum any value found into result
        rank -= (rank & -rank);
    }
    return result;
}
int arr[] = {7, 4, 6, 8};
int T[] = new int[arr.length];

for(int i=0; i<arr.length; i++)
    T[i] = 1;    

int sum = 1;     
for(int i=1; i<arr.length; i++){
    for(int j=0; j<i; j++){
        if(arr[i] > arr[j]){
            T[i] = T[i] + T[j]; 
        }
    }
    sum += T[i];
}
System.out.println(sum);