Dynamic Programming | Set 3 (Longest increasing subsequence)

Source: Internet
Author: User

In Dynamic Programming | Set 1 (overlapping Subproblems property) and Dynamic programming | In Set 2 (Optimal substructure property) We have discussed overlapping sub-problems and optimal substructure properties, and now we look at a problem that can be solved using dynamic programming: The Longest ascending subsequence (longest increasing Subsequence (LIS)).

The longest ascending subsequence problem, which is devoted to finding the longest subsequence in a given sequence, in ascending order of the elements in that subsequence. For example, the longest ascending subsequence of the sequence {10, 22, 9, 33, 21, 50, 41, 60, 80} has a length of 6, and the longest ascending subsequence is {10, 22, 33, 50, 60, 80}.

Optimal substructure:

Suppose arr[0..n-1] is an input array,L (i) is the length of the longest ascending subsequence of an array with the following subscript i , satisfying Arr[i] is part of the LIS, i.e. arr[i ] is the last element in the LIS, then L (i) can be recursively represented as:

L (i) = {1 + Max (L (j))} where J < I and Arr[j] < Arr[i] and if there is no such J then L (i) = 1

To get the length of a given array of LIS, we need to return max (L (i)) where 0 < i < n.

Therefore, the LIS problem has the optimal substructure property, so the problem can be solved by using the sub-problem method.

Overlapping subproblems:

The following is a simple recursive version of the LIS problem.

/* A Naive Recursive implementation of LIS problem */#include <stdio.h> #include <stdlib.h>/* To do use of rec Ursive calls, this function must return both things:1) Length of LIS ending with element arr[n-1].       We Use Max_ending_here-purpose 2) Overall maximum as the LIS may end with an element before arr[n-1] Max_ref is used this purpose. The value of LIS of full array of size n are stored in *max_ref which are our final result*/int _lis (int arr[], int n, int     *MAX_REF) {/* Base case */if (n = = 1) return 1; int res, max_ending_here = 1; Length of Lis ending with arr[n-1]/* Recursively get all LIS ending with arr[0], arr[1] ... ar[n-2].    If Arr[i-1] is smaller than arr[n-1], and Max ending with arr[n-1] needs to being updated, then update it */        for (int i = 1; i < n; i++) {res = _lis (arr, I, max_ref); if (Arr[i-1] < arr[n-1] && res + 1 > Max_ending_here) max_ending_here = RES + 1; }//Compare max_ending_here with the overall max.     and update the//overall Max if needed if (*max_ref < max_ending_here) *max_ref = Max_ending_here; Return length of LIS ending with arr[n-1] return max_ending_here;}     The wrapper function for _lis () int lis (int arr[], int n) {//The max variable holds the result int max = 1;     The function _lis () stores its result in Max _lis (arr, n, &max); Returns MAX return Max;}    /* Driver program to test above function */int main () {int arr[] = {10, 22, 9, 33, 21, 50, 41, 60};    int n = sizeof (arr)/sizeof (arr[0]);    printf ("Length of LIS is%d\n", LIS (arr, n));    GetChar (); return 0;}

Consider the above implementation, as follows: When the array size is 4 o'clock recursive tree, Lis (n) is the last element with N, the length of the LIS of the array.

It is not difficult to find that there are sub-problems which are repeated. Therefore, the problem has overlapping substructure properties, which can be prevented by memoization or tabulation to prevent the iterative calculation of sub-problems. As below, is the tabluated realization of LIS problem.

/* Dynamic programming implementation of LIS problem */#include <stdio.h> #include <stdlib.h>/* LIS () returns t He length of the longest increasing subsequence in arr[] of size n */int lis (int arr[], int n) {int *lis, I, J, MA   x = 0;    Lis = (int*) malloc (sizeof (int) * n);       /* Initialize LIS values for all indexes */for (i = 0; i < n; i++) lis[i] = 1;         /* Compute optimized LIS values in bottom up manner */for (i = 1; i < n; i++) for (j = 0; J < I, J + +)       if (Arr[i] > Arr[j] && lis[i] < Lis[j] + 1) lis[i] = Lis[j] + 1;    /* Pick maximum of all LIS values */for (i = 0; i < n; i++) if (Max < lis[i]) max = lis[i];    /* Free memory to avoid memory leak */free (LIS); return Max;}  /* Driver program to test above function */int main () {int arr[] = {10, 22, 9, 33, 21, 50, 41, 60};  int n = sizeof (arr)/sizeof (arr[0]); printf ("Length of LIS is%d\n", LIS (arr, n));  GetChar (); return 0;}

Note that the time complexity required for the above dynamic programming solution is O (n^2), in fact the LIS problem has an O (NLOGN) solution (see this). In this case, we did not discuss the solution of O (Nlogn), here, just use this article as a simple example of dynamic programming.

Dynamic Programming | Set 3 (Longest increasing subsequence)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.