求解最長遞增子序列長度|動態規劃+二分查找:C\C++實現

/* 求解最長遞增子序列長度 */
#include <iostream>
#include <limits>

using namespace std;

//int x[] = {1,-1,2,-3,4,-5,6,-7};
int x[] = {2, 1, 5, 3, 6, 4, 8, 9, 7};
int disp_array(int a[], int len);
int find_first_bigger(int a[], int last, int key);

int main()
{
    int len = sizeof(x)/sizeof(x[0]);
    int *z = new int(len + 1);
    /* z[i] = min(t|t:長度爲i的子序列的最後一個元素) */
    z[0] = std::numeric_limits<int>::min();
    for (int i = 1; i <= len; ++i)
    {
        z[i] = 0;
    }

    disp_array(x, len);
    disp_array(z, len + 1);

    int t, lislen = 0;
    for (int i = 0; i < len; ++i)
    {
        t = find_first_bigger(z, lislen, x[i]);
        if (t > lislen)
            z[++lislen] = x[i];     /* z[]中沒有比x[i]大的*/
        else
            z[t] = x[i];            /* z[t]第一個比x[i] */

    }

    disp_array(z, len + 1);
    cout << "LIS = " << lislen << endl;
    
    return 0;
}

/**
 * @brief 在數組a[0..last]中,自左向又查找第一個比key大的數的下標
 *        時間複雜度O(lg(n))
 *
 * @param a[]
 * @param last
 * @param key
 *
 * @return 返回下標,若是沒有比key大的則返回last+1
 */
int find_first_bigger(int a[], int last, int key)
{
    int m, p = -1, q = last + 1;
    /* assume: a[-1] < key <= a[last + 1] */
    while (p + 1 != q)
    {
        /* invartant: 0 <= p + 1 < q <= last + 1 && a[p] < key <= a[q]*/
        m = p + ((q - p)>>1);
        if (a[m] < key)
            p = m;
        else
            q = m;
    }

    return q;
}

int disp_array(int a[], int len)
{
    for (int i = 0; i < len; ++i)
    {
        cout << a[i];
        if (i == len -1)
            cout << endl;
        else
            cout << " ";
    }
    
}
相關文章
相關標籤/搜索