Problem Description:
Give a sequence to find the longest monotonically decreasing (or incrementing) subsequence.
For example, {10,22,9,33,21,50,41,60,80}
The length of the LIS is 6 and the LIS is {10,22,33,50,60,80}.
Optimal sub-structure:
For arrays of length N a[n] = {A0, a1, A2, ..., an-1}, suppose we want to ask for the maximum increment subsequence length at AJ End, set to L[j], then l[j] = max (L[i]) + 1, where I < J && A[i ] < A[j], that is, the range of I is 0 to j–1. Thus, in order to find the length of the maximal increment subsequence at AJ End, we need to traverse all positions I (0 to J-1) before J, identify A[i] < A[j], calculate I, which can produce the maximum l[i], and then we can find l[j]. Then I calculate the length of the maximal increment subsequence for each of the a[n], and the maximum of these lengths is the problem we ask--the maximum increment subsequence of array A.
overlapping sub-issues:
Realizing Lis by recursion
Below is the recursive tree
Lis (4)
/ | \
lis (3) lis (2) lis (1)
/ \ /
lis (2) lis (1) lis (1)
/
lis (1)
Some repetitive sub-problems are calculated several times. So we can use Memoization (memory storage) or hit the table to avoid recalculation of the same sub-problem. The following is the table to achieve the LIS, the time complexity of O (n^2).
int list (int arr[],int n)
{
int i,j,max;
max = 0;
for (i=1;i<=n;i++)
lis[i] = 1;
for (i=2;i<=n;i++)
{for
(j=1;j<i;j++)
{
if (Arr[i]>arr[j] && lis[i]<lis[j]+1)
Lis[i] = lis[j] + 1;
}
}
for (i=1;i<=n;i++)
if (Max < lis[i])
max = lis[i];
return Max;
Nlogn algorithm for longest ascending subsequence sequence
The search for array C can use binary lookup, which reduces the overall algorithm complexity. The time complexity is O (NLOGN).
Suppose there is a sequence d[1..9] = 2 1 5 3 6 4 8 9 7, it can be seen that the LIS length is 5. N
Try to find it step by step below.
We define a sequence B and then let i = 1 to 9 examine the sequence one at a.
In addition, we use a variable len to record the maximum number of times now.
First, put d[1] in order B, make b[1] = 2, that is, when there are only 11 digits 2, the smallest end of the LIS with a length of 1 is 2. Then Len=1
Then, put d[2] in an orderly place in B, so that b[1] = 1, that is, the minimum length of the LIS is 1,d[1]=2 is useless, it is easy to understand it. Then Len=1
Next, d[3] = 5,d[3]>b[1], so make b[1+1]=b[2]=d[3]=5, that is, the minimum end of the LIS with a length of 2 is 5, it is easy to understand. This time b[1..2] = 1, 5,len=2
Again, d[4] = 3, it just add to 1, 5, placed in the position of 1 is obviously inappropriate, because 1 is less than 3, the minimum length of the LIS is 1, so it is easy to infer that the length of the LIS min 1 is 2, so you can eliminate 3, this time b[1..2] = 5, 3,len = 1
Continue, d[5] = 6, it is behind 3, because b[2] = 3, and 6 is behind 3, so it is easy to infer b[3] = 6, then b[1..3] = 1, 3, 6, or it is easy to understand. Len = 3, OH.
6th, D[6] = 4, you see it between 3 and 6, so we can replace 6, get b[3] = 4. B[1..3] = 1, 3, 4, Len continues to be equal to 3
7th one, d[7] = 8, it's big, bigger than 4, uh. So b[4] = 8. Len becomes 4.
8th, D[8] = 9, get b[5] = 9, uh. Len continues to grow, to 5.
The last one, d[9] = 7, which is between b[3] = 4 and b[4] = 8, so we know that the latest b[4] =7,b[1..5] = 1, 3, 4, 7, 9,len = 5.
So we know the length of the LIS is 5.
!!!!! Attention. This 1,3,4,7,9 is not the LIS, it just stores the corresponding length to the minimum end of the LIS. With this at the end, we can insert data one at a-one place. Although the last d[9] = 7 update is not meaningful for this set of data, but if there are two numbers 8 and 9, then you can update 8 to d[5], 9 update to d[6], the length of the LIS is 6.
Then one thing should be discovered: inserting data in B is ordered and replaced without moving--that is, we can use a binary lookup to optimize the insertion time of each number to O (logn) ~~~~~ so the time complexity of the algorithm is reduced to O (NLOGN) ~.
int stack[10010];
int lis (int arr[],int n)
{
int i,top,mid,low,high;
top = 0;
Stack[0] =-1;
for (i=0;i<n;i++)
{
if (Arr[i]>stack[top])
stack[++top] = arr[i];
else
{Low
= 1;
High = top;
while (low <= high)
{
mid = (low + high)/2;
if (Arr[i] > Stack[mid]) Low
= mid + 1;
else high
= mid-1;
}
Stack[low] = Arr[i];
}
}
return top;
}