用二分法寻找最长连续单调递增子序列

来源:互联网 发布:婚礼摄影制作软件 编辑:程序博客网 时间:2024/04/29 19:48

/* 在由n个数组成的序列中,找出最长的单调递增子序列。子序列是连续的 */

#include <iostream>
using namespace std;

template <typename T>
void ArrCopy ( const T       arrSource[],
               const int&    startPosition,
               T *&          arrDestination,
               const int&    count )
{   //  从数组arrSource的第startPosition开始,复制count个元素到数组arrDestination
    if(arrDestination)
    {
        delete [] arrDestination;
        arrDestination = 0;
    }
    arrDestination = new T[count];
    int pos = 0;
    for ( int i = startPosition; i < startPosition+count; ++i )
    {
        arrDestination[pos++] = arrSource[i];
    }
}

template <typename T>
void PrintArr ( const T     arr[],
                const int&  size )
{   // 输出数组元素
    for( int i = 0; i < size; ++i )
    {
        cout << arr[i] << " ";
    }
    cout << endl;
}

template <typename T>
void GetMaxIncSubArr( const T       arr[],     //  源序列
                      const int&    size,      //  源序列的长度
                      T *&          sub,       //  生成的子序列
                      int&          subSize )  //  子序列的长度
{
    if ( size <= subSize )
    {
        return;
    }

    //  确定tempSubSize的值

    int tempSubSize = 1;

    int pointer = size >> 1;    //  pointer指向源序列的中部
    while( pointer + 1 < size &&
           arr[pointer+1] > arr[pointer] )
    {   //  若pointer右边的数大于pointer所指向的数,pointer右移,tempSubSize自增
        ++tempSubSize;
        ++pointer;
    }

    pointer = size >> 1;    //  指示器重新指向源序列的中部
    while( pointer > 0 &&
           arr[pointer-1] < arr[pointer] )
    {   //  若pointer左边的数小于pointer所指向的数,pointer左移,tempSubSize自增
        ++tempSubSize;
        --pointer;
    }

    //  pointer现在指向了位于源序列中部的单调递增子序列的首元素

    if ( tempSubSize > subSize )
    {   //  如果这个子序列比以往找到的子序列都要长,更新subSize
        subSize = tempSubSize;
        ArrCopy<T>(arr, pointer, sub, subSize);
    }

    int * left = 0; // left是位于源序列中部的单调递增子序列的左边部分
    int leftSize = pointer;
    if ( leftSize > subSize )
    {
        ArrCopy<T>(arr, 0, left, leftSize);
    }

    int * right = 0;    // right是位于源序列中部的单调递增子序列的右边部分
    int rightSize = size - pointer - subSize;
    if ( rightSize > subSize )
    {
        ArrCopy<T>(arr, pointer+subSize, right, rightSize);
    }

    if ( pointer > subSize )
    {   //  对左边部分计算最长的单调递增子序列
        GetMaxIncSubArr(left, leftSize, sub, subSize);
        delete [] left;
    }
    if(rightSize > subSize)
    {   //  对右边部分计算最长的单调递增子序列
        GetMaxIncSubArr(right, rightSize, sub, subSize);
        delete [] right;
    }
}


int main(int argc, char* argv[])
{
    int arr[] = {0,1,2,3,4,5,6,7,8,9};
    int size = sizeof(arr)/sizeof(int);
    int* sub = 0;
    int subSize = 0;
    GetMaxIncSubArr<int>(arr, size, sub, subSize);
    cout << subSize << endl;
    PrintArr<int>(sub, subSize);
    delete [] sub;

    cin.get();   
    return 0;
}

原创粉丝点击