Dynamic programming of the longest increment sub-sequence

Source: Internet
Author: User

    Topic one: Given an array of length n, find the longest monotonically incrementing subsequence (not necessarily contiguous, but not in a chaotic order). and returns the length of the monotonically increasing subsequence.
    For example: Given an array of length 8 a{1,3,5,2,4,6,7,8}, its longest monotonically incrementing subsequence is {1,2,4,6,7,8}, and we return its length 6.
    Topic Two: On the basis of topic one, we want to return the elements in the subsequence. For example, given an array of length 8 a{1,3,5,2,4,6,7,8}, we return monotonically incrementing the subsequence {1,2,4,6,7,8}.
    Parsing: We use the idea of dynamic programming to solve this problem, assuming that the given array is nums and its length is n. Sets a secondary array len, whose length is the same as the given array. The length of the longest monotonically incrementing subsequence that ends with the element is stored in the secondary array, as shown in:
 So how do we get the values in the array len. Initializes each value in the Len array to 1, and when traversing the nums array, each traversal of a number updates the value of the corresponding position in the Len array. If we are currently visiting Nums[i]. You need to update the value in Len[i], we need to revisit the nums array before i-1, if I-1] is greater than the number of nums[i [nums[j], compared with the number of nums[i], and the len[j]+1 value is greater than len[i]. The value of Len[i] is updated to the value of len[j]+1. The final result is the value of the longest monotonically incrementing subsequence at the end of the element. For example, when we update len[2], we need to access nums[0] and nums[1], when accessing nums[0], because Nums[0] is less than nums[2], and len[2] is less than len[0]+1, so this step we update the len[2] to 2, When accessing Nums[1], because Nums[1] is less than nums[2], and len[2] is less than len[1]+1, so this step we update the len[2] to 3, then the value of the last Len[2] is 3, which means that the length of the longest increment subsequence ending with nums[2] is 3. When we update len[3], we need to access nums[0], nums[1] and nums[2], when accessing nums[0], because nums[3] is greater than nums[0], and len[3] is less than len[0]+1, so this step len[3] is updated to 2, When accessing Nums[1], because nums[3] is less than nums[0], len[3] does not need to be updated in this step. Similarly, when accessing nums[2], len[3] does not need to be updated. The last len[3] is 2. As shown in. This method has a time complexity of O (n*n) because we need to access the previous I-1 elements for the value of update len[i]. where n represents the length of the array. The code looks like this: 
int maxlongsub (vector<int> &nums) {//When the array is empty, returns 0IF (Nums.empty ()) return 0;int size = nums.size ();vector< Int> len (size);//len array len[0] = 1;//Update value for each len[i] for (int i = 1; i < size; ++i) {Len[i] = 1;//access Before I-1 elements for (int j = 0; J < I; ++J) {//Determines whether the current len[i] needs to be updated. if (Nums[i] > Nums[j] && len[i] < Len[j] + 1) {Len[i] = Len[j] + 1;}}} int index = 0;//Len[index] Maximum value for (int i = 1; i < size; ++i) {if (Len[i] > Len[index]) {index = i;}} return Len[index];}
The above code uses the test case for Leetcode No. 300, with a total of 22 test cases. Run time is 112ms. Can we reduce the complexity of time? The answer is yes, the time complexity of the above code is O (n*n). We can reduce the complexity of time to O (Nlogn). Because every time we update len[i], we need sequential access to the first i-1 elements, and actually some accesses are unnecessary. We set an ordered array of res, the array is initialized to NULL, each time we access the elements in the nums, we use that element to look in an ordered array, find the first larger element than the element, and then update the value in the ordered array to the value of that element, if there are no elements larger than that element in the array, That is, the element is larger than the last element of an ordered array, we insert this element at the end of an ordered array, and the length of the last ordered array is the length of the longest increment subsequence. Because the time complexity of finding operations in an ordered array is O (Logn), the time complexity of this thought is O (Nlogn). :
  So why is the length of the last res array the length of the longest increment subsequence? Because the element at the end of the res is the maximum value of the element that is currently accessed, when the next element is accessed, if the value of the next element is greater than the value of the element at the end of the res, we can find an incremented sub-sequence that is longer than the current res.size (). If the value of the next element is smaller than the value of the element at the end of the res, you can certainly find the first value greater than the element, and we update the element in res with this element. The code is as follows:  
//returns the position of the given element to be inserted int getPos (vector<int> &nums, int val) {int low = 0; int high = Nums.size ()-1;while (Low <= high) {int mid = (low + high)/2;if (Nums[mid] < val) {low = mid + 1;} Else{high = Mid-1;}} return low;} int Lengthoflis (vector<int>& nums) {if (Nums.empty ()) return 0;vector<int> Res;res.push_back (Nums[0]) ;//Add the first element for (int i = 1; i < nums.size (); ++i) {int pos = GetPos (res, nums[i]);//If greater than the last element if (pos = = Res.size ()) {RES.P Ush_back (Nums[i]);} Else{res[pos] = Nums[i];}}   return Res.size ();} 
We use the test case in Leetcode, with a run time of 4ms, which is much better than the 112ms of the first method.
   On the basis of the first method, we can answer topic two and set up an auxiliary array pre, which stores the subscript of the second-to-last element in the longest increment subsequence ending at the current position. The code is as follows:
int maxlongsub (vector<int> &nums) {if (Nums.empty ()) return 0;int size = nums.size ();vector<int> Len ( Size);vector<int> pre (size,-1); len[0] = 1;pre[0] = -1;for (int i = 1; i < size; ++i) {Len[i] = 1;for (int j = 0; J < I; ++J) {if (Nums[i] > Nums[j] && len[i] < Len[j] + 1) {Len[i] = Len[j] + 1;pre[i] = j;}}} int index = 0;for (int i = 1; i < size; ++i) {if (Len[i] > Len[index]) {index = i;}} Vector<int> res;while (Pre[index]! =-1) {Res.push_back (Nums[index]); index = Pre[index];} Res.push_back (Nums[index]); for (int i = Res.size ()-1; i > 0; i.) {cout << res[i] << "";} cout << res[0] << endl;return len[index];}
The element in the last res in method two is a maximum increment subsequence.

Dynamic programming of the longest increment sub-sequence

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.