Editing Longest increasing subsequence

Jump to: navigation, search

Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.

The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then save the changes below to finish undoing the edit.
Latest revision Your text
Line 20: Line 20:
  
 
===Optimal substructure===
 
===Optimal substructure===
The value for <math>\operatorname{LIS}'(i)</math> consists of either:
+
The dynamic substructure is not too hard to see. The value for <math>\operatorname{LIS}'(i)</math> consists of either:
 
* the element <math>x_i</math> alone, which always forms an increasing subsequence by itself, or
 
* the element <math>x_i</math> alone, which always forms an increasing subsequence by itself, or
 
* the element <math>x_i</math> tacked on to the end of an increasing subsequence ending with <math>x_j</math>, where <math>j < i</math> and <math>x_j \leq x_i</math> (for the non-strict case) or <math>x_j < x_i</math> (for the strict case).
 
* the element <math>x_i</math> tacked on to the end of an increasing subsequence ending with <math>x_j</math>, where <math>j < i</math> and <math>x_j \leq x_i</math> (for the non-strict case) or <math>x_j < x_i</math> (for the strict case).
Line 42: Line 42:
 
The LIS of the entire sequence <math>x</math> is then just the largest of all <math>\operatorname{LIS}'</math> values.
 
The LIS of the entire sequence <math>x</math> is then just the largest of all <math>\operatorname{LIS}'</math> values.
  
 +
===Analysis===
 +
====Time====
 
If only the length is desired, the above formula becomes
 
If only the length is desired, the above formula becomes
 
:<math>\operatorname{LIS\_len}'(i) = 1 + \max (\{\operatorname{LIS\_len}'(j) \mid 1 \leq j < i \wedge x_j \leq x_i\} \cup \{0\})</math>
 
:<math>\operatorname{LIS\_len}'(i) = 1 + \max (\{\operatorname{LIS\_len}'(j) \mid 1 \leq j < i \wedge x_j \leq x_i\} \cup \{0\})</math>
 
+
Thus, computing the <math>i^{\text{th}}</math> entry takes <math>O(i)</math> time to compute, giving <math>O(1) + O(2) + ... + O(n) = O(n^2)</math> time overall.
====Pseudocode====
+
(This is for the non-strict case.)
+
<pre>
+
input x
+
n &larr; length of x
+
for each i &isin; [1..n]
+
    lis[i] &larr; 1
+
    for each j &isin; [1..(i-1)]
+
          if x[i] &ge; x[j]
+
          lis[i] &larr; max(lis[i],1+lis[j])
+
return max element of lis
+
</pre>
+
 
+
===Analysis===
+
====Time====
+
With the length-only formula above, computing the <math>i^{\text{th}}</math> entry takes <math>O(i)</math> time to compute, giving <math>O(1) + O(2) + ... + O(n) = O(n^2)</math> time overall.
+
  
 
This bound still holds when computing the LIS itself, but since we probably wish to avoid needless copying and concatenation of sequences, a better way is to, instead of storing the <math>\operatorname{LIS}'</math> values themselves in the table, simply storing their lengths as well as making a note of the next-to-last element of the sequence (or storing a zero if there is none) so that we can backtrack to reconstruct the original sequence.
 
This bound still holds when computing the LIS itself, but since we probably wish to avoid needless copying and concatenation of sequences, a better way is to, instead of storing the <math>\operatorname{LIS}'</math> values themselves in the table, simply storing their lengths as well as making a note of the next-to-last element of the sequence (or storing a zero if there is none) so that we can backtrack to reconstruct the original sequence.
Line 77: Line 63:
  
 
Now let's see how the array <math>a</math> allows us to find the length of the LIS. We consider the elements of <math>x</math> one at a time starting from <math>x_1</math>. For each element <math>x_i</math> we consider, we notice that we want to find the ''longest increasing subsequence so far discovered that ends on a value less than or equal to <math>x_i</math>''. To do this, we perform a [[binary search]] on the array <math>a</math> for the largest index <math>j</math> for which <math>a_j \leq x_i</math>, or return <math>j=0</math> if no such index exists (empty sequence). Then, we know we can obtain an increasing subsequence of length <math>j+1</math> by appending <math>x_i</math> to the end of the increasing subsequence of length <math>j</math> ending at on value <math>a_j</math>; if there is no such value then we get an increasing subsequence of length 1 by taking <math>x_i</math> by itself. What effect does this have on <math>a</math>? We know that <math>x_i < a_{j+1}</math>, and we also know that we have obtained an increasing subsequence of length <math>j+1</math> whose last element is <math>x_i</math>, which is therefore ''better'' than what we have on file for <math>a_{j+1}</math>. Therefore, we update <math>a_{j+1}</math> so that it equals <math>x_i</math>. Note that after this operation, ''<math>a</math> will still be sorted'', because <math>x_i</math> was originally less than <math>a_{j+2}</math>, so <math>a_{j+1}</math> will be less after the update, and <math>a_{j+1}</math> will still be greater than or equal to <math>a_j</math>, because <math>x_i \geq a_j</math>. After iterating through all elements of <math>x</math> and updating <math>a</math> at each step, the algorithm terminates.
 
Now let's see how the array <math>a</math> allows us to find the length of the LIS. We consider the elements of <math>x</math> one at a time starting from <math>x_1</math>. For each element <math>x_i</math> we consider, we notice that we want to find the ''longest increasing subsequence so far discovered that ends on a value less than or equal to <math>x_i</math>''. To do this, we perform a [[binary search]] on the array <math>a</math> for the largest index <math>j</math> for which <math>a_j \leq x_i</math>, or return <math>j=0</math> if no such index exists (empty sequence). Then, we know we can obtain an increasing subsequence of length <math>j+1</math> by appending <math>x_i</math> to the end of the increasing subsequence of length <math>j</math> ending at on value <math>a_j</math>; if there is no such value then we get an increasing subsequence of length 1 by taking <math>x_i</math> by itself. What effect does this have on <math>a</math>? We know that <math>x_i < a_{j+1}</math>, and we also know that we have obtained an increasing subsequence of length <math>j+1</math> whose last element is <math>x_i</math>, which is therefore ''better'' than what we have on file for <math>a_{j+1}</math>. Therefore, we update <math>a_{j+1}</math> so that it equals <math>x_i</math>. Note that after this operation, ''<math>a</math> will still be sorted'', because <math>x_i</math> was originally less than <math>a_{j+2}</math>, so <math>a_{j+1}</math> will be less after the update, and <math>a_{j+1}</math> will still be greater than or equal to <math>a_j</math>, because <math>x_i \geq a_j</math>. After iterating through all elements of <math>x</math> and updating <math>a</math> at each step, the algorithm terminates.
 
===Pseudocode===
 
(Non-strict case.)
 
<pre>
 
input x
 
n &larr; length of x
 
result &larr; 0
 
a[0] &larr; -&#8734;
 
for each i &isin; [1..n]
 
    a[i] &larr; +&#8734;
 
for each i &isin; [1..n]
 
    l &larr; 0
 
    u &larr; n
 
    while u &gt; l
 
          if a[&lfloor;(l+u)/2&rfloor;] &le; x[i]
 
              l &larr; 1 + &lfloor;(l+u)/2&rfloor;
 
          else
 
              u &larr; &lfloor;(l+u)/2&rfloor;
 
    a[l] &larr; x[i]
 
    result &larr; max(result,l)
 
return result
 
</pre>
 
  
 
===Analysis===
 
===Analysis===

Please note that all contributions to PEGWiki are considered to be released under the Attribution 3.0 Unported (see PEGWiki:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!

Cancel | Editing help (opens in new window)