{"id":25350,"date":"2017-10-15T17:10:35","date_gmt":"2017-10-15T11:40:35","guid":{"rendered":"https:\/\/www.wikitechy.com\/technology\/?p=25350"},"modified":"2018-10-31T16:26:46","modified_gmt":"2018-10-31T10:56:46","slug":"python-programming-longest-increasing-subsequence","status":"publish","type":"post","link":"https:\/\/www.wikitechy.com\/technology\/python-programming-longest-increasing-subsequence\/","title":{"rendered":"Longest Increasing Subsequence"},"content":{"rendered":"<p><span style=\"color: #003300;\"><strong>Longest Increasing Subsequence:<\/strong><\/span><\/p>\n<p>We have discussed <a href=\"https:\/\/www.wikitechy.com\/technology\/python-programming-overlapping-subproblems-property\/\">Overlapping Subproblems<\/a> and<a href=\"https:\/\/www.wikitechy.com\/technology\/optimal-substructure-property\/\" target=\"_blank\" rel=\"noopener\"> Optimal Substructure<\/a> properties respectively.<span id=\"more-12832\"><\/span><\/p>\n<p>Let us discuss <strong>Longest Increasing Subsequence<\/strong> (LIS) problem as an example problem that can be solved using <a href=\"https:\/\/www.wikitechy.com\/technology\/python-programming-min-cost-path\/\" target=\"_blank\" rel=\"noopener\">Dynamic Programming<\/a>.<br \/>\nThe Longest Increasing Subsequence (<strong>LIS<\/strong>) problem is to find the length of the longest subsequence of a given sequence such that all elements of the subsequence are <a href=\"https:\/\/www.wikitechy.com\/technology\/algorithm-in-c-median-of-two-sorted-arrays\/\" target=\"_blank\" rel=\"noopener\">sorted<\/a> in increasing order. <strong>For example<\/strong>, the length of LIS for {10, 22, 9, 33, 21, 50, 41, 60, 80} is 6 and LIS is {10, 22, 33, 50, 60, 80}<\/p>\n<p><img fetchpriority=\"high\" decoding=\"async\" class=\"aligncenter size-full wp-image-25327\" src=\"https:\/\/www.wikitechy.com\/technology\/wp-content\/uploads\/2017\/05\/Longest-Increasing-Subsequence.png\" alt=\"Longest-Increasing-Subsequence\" width=\"779\" height=\"89\" srcset=\"https:\/\/www.wikitechy.com\/technology\/wp-content\/uploads\/2017\/05\/Longest-Increasing-Subsequence.png 779w, https:\/\/www.wikitechy.com\/technology\/wp-content\/uploads\/2017\/05\/Longest-Increasing-Subsequence-300x34.png 300w, https:\/\/www.wikitechy.com\/technology\/wp-content\/uploads\/2017\/05\/Longest-Increasing-Subsequence-768x88.png 768w\" sizes=\"(max-width: 779px) 100vw, 779px\" \/><\/p>\n<p><span style=\"color: #800000;\"><strong>More Examples:<\/strong><\/span><\/p>\n<pre>Input  : arr[] = {3, 10, 2, 1, 20}\r\nOutput : Length of LIS = 3\r\nThe longest increasing subsequence is 3, 10, 20\r\n\r\nInput  : arr[] = {3, 2}\r\nOutput : Length of LIS = 1\r\nThe longest increasing subsequences are {3} and {2}\r\n\r\nInput : arr[] = {50, 3, 10, 7, 40, 80}\r\nOutput : Length of LIS = 4\r\nThe longest increasing subsequence is {3, 7, 40, 80}<\/pre>\n[ad type=\u201dbanner\u201d]\n<h3 id=\"optimal-substructure\"><span style=\"color: #000080;\"><strong>Optimal Substructure:<\/strong><\/span><\/h3>\n<p>Let <strong>arr[0..n-1]<\/strong> be the input <a href=\"https:\/\/www.wikitechy.com\/tutorials\/javascript\/remove-empty-elements-from-an-array-in\" target=\"_blank\" rel=\"noopener\">array<\/a> and L(i) be the length of the LIS ending at index i such that arr[i] is the last element of the LIS.<br \/>\nThen, L(i) can be recursively written as:<br \/>\n<strong>L(i) = 1 + max( L(j) )<\/strong> where 0 < j < i and arr[j] < arr[i]; or<br \/>\n<strong>L(i) = 1<\/strong>, if no such j exists.<br \/>\nTo find the LIS for a given array, we need to return <strong>max(L(i))<\/strong> where 0 < i < n.<br \/>\nThus, we see the LIS problem satisfies the optimal substructure property as the main problem can be solved using solutions to subproblems.<\/p>\n<p>Following is a simple recursive implementation of the LIS problem. It follows the recursive structure discussed above.<\/p>\n<p><span style=\"color: #993300;\"><strong>Python Programming<\/strong><\/span><\/p>\n[pastacode lang=\u201dpython\u201d manual=\u201d%23%20A%20naive%20Python%20based%20recursive%20implementation%20of%20LIS%20problem%0A%20%0Aglobal%20max_lis_length%20%23%20stores%20the%20final%20LIS%0A%20%0A%23%20Recursive%20implementation%20for%20calculating%20the%20LIS%0Adef%20_lis(arr%2C%20n)%3A%0A%20%20%20%20%23%20Following%20declaration%20is%20needed%20to%20allow%20modification%0A%20%20%20%20%23%20of%20the%20global%20copy%20of%20max_lis_length%20in%20_lis()%0A%20%20%20%20global%20max_lis_length%0A%20%0A%20%20%20%20%23%20Base%20Case%0A%20%20%20%20if%20n%20%3D%3D%201%3A%0A%20%20%20%20%20%20%20%20return%201%0A%20%0A%20%20%20%20current_lis_length%20%3D%201%0A%20%0A%20%20%20%20for%20i%20in%20xrange(0%2C%20n-1)%3A%0A%20%20%20%20%20%20%20%20%23%20Recursively%20calculate%20the%20length%20of%20the%20LIS%0A%20%20%20%20%20%20%20%20%23%20ending%20at%20arr%5Bi%5D%0A%20%20%20%20%20%20%20%20subproblem_lis_length%20%3D%20_lis(arr%2C%20i)%0A%20%0A%20%20%20%20%20%20%20%20%23%20Check%20if%20appending%20arr%5Bn-1%5D%20to%20the%20LIS%0A%20%20%20%20%20%20%20%20%23%20ending%20at%20arr%5Bi%5D%20gives%20us%20an%20LIS%20ending%20at%0A%20%20%20%20%20%20%20%20%23%20arr%5Bn-1%5D%20which%20is%20longer%20than%20the%20previously%0A%20%20%20%20%20%20%20%20%23%20calculated%20LIS%20ending%20at%20arr%5Bn-1%5D%0A%20%20%20%20%20%20%20%20if%20arr%5Bi%5D%20%3C%20arr%5Bn-1%5D%20and%20%5C%0A%20%20%20%20%20%20%20%20%20%20%20%20current_lis_length%20%3C%20(1%2Bsubproblem_lis_length)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20current_lis_length%20%3D%20(1%2Bsubproblem_lis_length)%0A%20%0A%20%20%20%20%23%20Check%20if%20currently%20calculated%20LIS%20ending%20at%0A%20%20%20%20%23%20arr%5Bn-1%5D%20is%20longer%20than%20the%20previously%20calculated%0A%20%20%20%20%23%20LIS%20and%20update%20max_lis_length%20accordingly%0A%20%20%20%20if%20(max_lis_length%20%3C%20current_lis_length)%3A%0A%20%20%20%20%20%20%20%20max_lis_length%20%3D%20current_lis_length%0A%20%0A%20%20%20%20return%20current_lis_length%0A%20%0A%23%20The%20wrapper%20function%20for%20_lis()%0Adef%20lis(arr%2C%20n)%3A%0A%20%0A%20%20%20%20%23%20Following%20declaration%20is%20needed%20to%20allow%20modification%0A%20%20%20%20%23%20of%20the%20global%20copy%20of%20max_lis_length%20in%20lis()%0A%20%20%20%20global%20max_lis_length%0A%20%0A%20%20%20%20max_lis_length%20%3D%201%20%23%20stores%20the%20final%20LIS%0A%20%0A%20%20%20%20%23%20max_lis_length%20is%20declared%20global%20at%20the%20top%0A%20%20%20%20%23%20so%20that%20it%20can%20maintain%20its%20value%0A%20%20%20%20%23%20between%20the%20recursive%20calls%20of%20_lis()%0A%20%20%20%20_lis(arr%20%2C%20n)%0A%20%0A%20%20%20%20return%20max_lis_length%0A%20%0A%23%20Driver%20program%20to%20test%20the%20functions%20above%0Adef%20main()%3A%0A%20%20%20%20arr%20%3D%20%5B10%2C%2022%2C%209%2C%2033%2C%2021%2C%2050%2C%2041%2C%2060%5D%0A%20%20%20%20n%20%3D%20len(arr)%0A%20%20%20%20print%20%22Length%20of%20LIS%20is%22%2C%20lis(arr%2C%20n)%0A%20%0Aif%20__name__%3D%3D%22__main__%22%3A%0A%20%20%20%20main()\u201d message=\u201dPython\u201d highlight=\u201d\u201d provider=\u201dmanual\u201d\/]\n<h3 id=\"output\"><span style=\"color: #008000;\"><strong>Output :<\/strong><\/span><\/h3>\n<pre>Length of LIS is 5<\/pre>\n<h3 id=\"overlapping-subproblems\"><span style=\"color: #000080;\"><strong>Overlapping Subproblems :<\/strong><\/span><\/h3>\n<p>Considering the above implementation, following is recursion tree for an array of size 4. <strong>lis(n)<\/strong> gives us the length of LIS for arr[].<\/p>\n<pre>              lis(4)\r\n        \/        |     \\\r\n      lis(3)    lis(2)   lis(1)\r\n     \/   \\        \/\r\n   lis(2) lis(1) lis(1)\r\n   \/\r\nlis(1)\r\n<\/pre>\n<p>We can see that there are many subproblems which are solved again and again. So this problem has Overlapping Substructure property and recomputation of same subproblems can be avoided by either using Memorization or Tabulation. Following is a tabluated implementation for the LIS problem.<\/p>\n[ad type=\u201dbanner\u201d]\n<p><span style=\"color: #993300;\"><strong>Python\u00a0Programming<\/strong><\/span><\/p>\n[pastacode lang=\u201dpython\u201d manual=\u201d%23%20Dynamic%20programming%20Python%20implementation%20of%20LIS%20problem%0A%20%0A%23%20lis%20returns%20length%20of%20the%20longest%20increasing%20subsequence%0A%23%20in%20arr%20of%20size%20n%0Adef%20lis(arr)%3A%0A%20%20%20%20n%20%3D%20len(arr)%0A%20%0A%20%20%20%20%23%20Declare%20the%20list%20(array)%20for%20LIS%20and%20initialize%20LIS%0A%20%20%20%20%23%20values%20for%20all%20indexes%0A%20%20%20%20lis%20%3D%20%5B1%5D*n%0A%20%0A%20%20%20%20%23%20Compute%20optimized%20LIS%20values%20in%20bottom%20up%20manner%0A%20%20%20%20for%20i%20in%20range%20(1%20%2C%20n)%3A%0A%20%20%20%20%20%20%20%20for%20j%20in%20range(0%20%2C%20i)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20arr%5Bi%5D%20%3E%20arr%5Bj%5D%20and%20lis%5Bi%5D%3C%20lis%5Bj%5D%20%2B%201%20%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20lis%5Bi%5D%20%3D%20lis%5Bj%5D%2B1%0A%20%0A%20%20%20%20%23%20Initialize%20maximum%20to%200%20to%20get%20the%20maximum%20of%20all%0A%20%20%20%20%23%20LIS%0A%20%20%20%20maximum%20%3D%200%0A%20%0A%20%20%20%20%23%20Pick%20maximum%20of%20all%20LIS%20values%0A%20%20%20%20for%20i%20in%20range(n)%3A%0A%20%20%20%20%20%20%20%20maximum%20%3D%20max(maximum%20%2C%20lis%5Bi%5D)%0A%20%0A%20%20%20%20return%20maximum%0A%23%20end%20of%20lis%20function%0A%20%0A%23%20Driver%20program%20to%20test%20above%20function%0Aarr%20%3D%20%5B10%2C%2022%2C%209%2C%2033%2C%2021%2C%2050%2C%2041%2C%2060%5D%0Aprint%20%22Length%20of%20lis%20is%22%2C%20lis(arr)\u201d message=\u201dPython\u201d highlight=\u201d\u201d provider=\u201dmanual\u201d\/]\n<h3 id=\"output-2\"><span style=\"color: #008000;\"><strong>Output :<\/strong><\/span><\/h3>\n<pre>Length of lis is 5<\/pre>\n<p>Note that the time complexity of the above Dynamic Programming (DP) solution is <strong>O(n^2)<\/strong> and there is a <strong>O(nLogn)<\/strong> solution for the LIS problem.<\/p>\n[ad type=\u201dbanner\u201d]\n","protected":false},"excerpt":{"rendered":"<p>Python Programming &#8211; Longest Increasing Subsequence &#8211; Dynamic Programming &#8211; LIS problem is to find the length of the longest subsequence of a given sequence<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1,70145,83517],"tags":[72847,72842,72993,70483,72848,72840,72846,72994,72843,72992,72854,72844,72850,72839,72977,72979,72995,72978,72975,72981,72980,72976,72852,72855,72853,72851],"class_list":["post-25350","post","type-post","status-publish","format-standard","hentry","category-coding","category-dynamic-programming","category-python-programming","tag-concept-of-dynamic-programming","tag-define-dynamic-programming","tag-definition-of-dynamic-programming-in-python","tag-dynamic-programming","tag-dynamic-programming-code-generation-algorithm","tag-dynamic-programming-definition","tag-dynamic-programming-in-data-structure","tag-dynamic-programming-in-python","tag-dynamic-programming-problems","tag-dynamic-programming-python","tag-dynamic-programming-set-1","tag-dynamic-programming-software","tag-explain-dynamic-programming","tag-how-to-solve-dynamic-programming-problems","tag-longest-increasing-subsequence-c","tag-longest-increasing-subsequence-code","tag-longest-increasing-subsequence-in-python","tag-longest-increasing-subsequence-java","tag-longest-increasing-subsequence-nlogn","tag-longest-increasing-subsequence-recursive","tag-longest-increasing-subsequence-youtube","tag-longest-increasing-subsequences","tag-problems-on-dynamic-programming","tag-simple-dynamic-programming-example","tag-types-of-dynamic-programming","tag-youtube-dynamic-programming"],"_links":{"self":[{"href":"https:\/\/www.wikitechy.com\/technology\/wp-json\/wp\/v2\/posts\/25350","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.wikitechy.com\/technology\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.wikitechy.com\/technology\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.wikitechy.com\/technology\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.wikitechy.com\/technology\/wp-json\/wp\/v2\/comments?post=25350"}],"version-history":[{"count":0,"href":"https:\/\/www.wikitechy.com\/technology\/wp-json\/wp\/v2\/posts\/25350\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.wikitechy.com\/technology\/wp-json\/wp\/v2\/media?parent=25350"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.wikitechy.com\/technology\/wp-json\/wp\/v2\/categories?post=25350"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.wikitechy.com\/technology\/wp-json\/wp\/v2\/tags?post=25350"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}