# LeetCode 300. Longest ascending subsequence

### 9-8 LIS problem long increasing subsequence

##### Title: LeetCode 300. Longest ascending subsequence

Given an unordered array of integers, find the length of the longest ascending subsequence.

Example:

Input: [10,9,2,5,3,7101,18]
Output: 4
Explanation: the longest ascending subsequence is [2,3,7101], and its length is 4.
Explain:

There may be multiple combinations of the longest ascending subsequences. You only need to output the corresponding length.
The time complexity of your algorithm should be O(n2).
Advanced: can you reduce the time complexity of the algorithm to O(n log n)?

##### LIS(i) = when (J < I), Max {1 + LIS (J) if nums [i] > nums [J]}
``````import java.util.Arrays;

/// 300. Longest Increasing Subsequence
/// https://leetcode.com/problems/longest-increasing-subsequence/description/
///Memory search
///Time complexity: O(n^2)
///Spatial complexity: O(n)
public class Solution1 {

private int[] memo;

public int lengthOfLIS(int[] nums) {

if(nums.length == 0)
return 0;

memo = new int[nums.length];
Arrays.fill(memo, -1);
int res = 1;
for(int i = 0 ; i < nums.length ; i ++)
res = Math.max(res, getMaxLength(nums, i));

return res;
}

// Length of the longest ascending subsequence ending in nums[index]
private int getMaxLength(int[] nums, int index){

if(memo[index] != -1)
return memo[index];

int res = 1;
for(int i = 0 ; i <= index-1 ; i ++)
if(nums[index] > nums[i])
res = Math.max(res, 1 + getMaxLength(nums, i));

return memo[index] = res;
}

public static void main(String[] args) {

int nums1[] = {10, 9, 2, 5, 3, 7, 101, 18};
System.out.println((new Solution1()).lengthOfLIS(nums1));
// 4

// ---

int nums2[] = {4, 10, 4, 3, 8, 9};
System.out.println((new Solution1()).lengthOfLIS(nums2));
// 3

// ---

int nums3[] = {2, 2};
System.out.println((new Solution1()).lengthOfLIS(nums3));
// 1

// ---

int nums4[] = {1, 3, 6, 7, 9, 4, 10, 5, 6};
System.out.println((new Solution1()).lengthOfLIS(nums4));
// 6
}
}
``````
``````import java.util.Arrays;

/// 300. Longest Increasing Subsequence
/// https://leetcode.com/problems/longest-increasing-subsequence/description/
///Memory search
///Time complexity: O(n^2)
///Spatial complexity: O(n)
public class Solution2 {

public int lengthOfLIS(int[] nums) {

if(nums.length == 0)
return 0;

// memo[i] represents the length of the longest ascending subsequence ending in nums[i]
int memo[] = new int[nums.length];
Arrays.fill(memo, 1);
for(int i = 1 ; i < nums.length ; i ++)
for(int j = 0 ; j < i ; j ++)
if(nums[i] > nums[j])
memo[i] = Math.max(memo[i], 1 + memo[j]);

int res = memo;
for(int i = 1 ; i < nums.length ; i ++)
res = Math.max(res, memo[i]);

return res;
}

public static void main(String[] args) {

int nums1[] = {10, 9, 2, 5, 3, 7, 101, 18};
System.out.println((new Solution2()).lengthOfLIS(nums1));
// 4

// ---

int nums2[] = {4, 10, 4, 3, 8, 9};
System.out.println((new Solution2()).lengthOfLIS(nums2));
// 3

// ---

int nums3[] = {2, 2};
System.out.println((new Solution2()).lengthOfLIS(nums3));
// 1

// ---

int nums4[] = {1, 3, 6, 7, 9, 4, 10, 5, 6};
System.out.println((new Solution2()).lengthOfLIS(nums4));
// 6
}
}

``````
``````import java.util.Arrays;

/// 300. Longest Increasing Subsequence
/// https://leetcode.com/problems/longest-increasing-subsequence/description/
///
///In this chapter, we introduce the dynamic programming method to solve the LIS problem. The time complexity is O(nlogn)
///LIS has a classical and ingenious dynamic programming method, whose time complexity is O(nlogn)
///Here are the reference code and simple notes. If you need more detailed explanation, you can search and learn on the Internet by yourself
///Through this example, let's also understand how to change the state definition of dynamic planning,
///It brings about significant differences in problem-solving methods, even huge optimizations on the order of time complexity
///
///Time complexity: O(nlogn)
///Spatial complexity: O(n)
public class Solution {

public int lengthOfLIS(int[] nums) {

if(nums.length == 0)
return 0;

// dp[i] represents the increment subsequence with the longest length of I and the minimum value of the last number
int dp[] = new int[nums.length + 1];
Arrays.fill(dp, Integer.MIN_VALUE);

int len = 1;
dp = nums;
for(int i = 1 ; i < nums.length ; i ++)
if(nums[i] > dp[len]){
len ++;
dp[len] = nums[i];
}
else{
// Our dp array will be a monotonically increasing array, so we can use binary search method
int index = lowerBound(dp, 0, len, nums[i]);
if(dp[index] != nums[i])
dp[index] = Math.min(dp[index], nums[i]);
}

return len;
}

// lowerBound finds the index of the first element greater than or equal to target in the range of arr[l...r]
private int lowerBound(int[] arr, int l, int r, int target){

int left = l, right = r + 1;
while(left != right){
int mid = left + (right - left) / 2;
if(arr[mid] >= target)
right = mid;
else // arr[mid] < target
left = mid + 1;
}
return left;
}

public static void main(String[] args) {

int nums1[] = {10, 9, 2, 5, 3, 7, 101, 18};
System.out.println((new Solution()).lengthOfLIS(nums1));
// 4

// ---

int nums2[] = {4, 10, 4, 3, 8, 9};
System.out.println((new Solution()).lengthOfLIS(nums2));
// 3

// ---

int nums3[] = {2, 2};
System.out.println((new Solution()).lengthOfLIS(nums3));
// 1

// ---

int nums4[] = {1, 3, 6, 7, 9, 4, 10, 5, 6};
System.out.println((new Solution()).lengthOfLIS(nums4));
// 6
}
}
``````

Keywords: Java Programming

Added by VapiD on Wed, 18 Dec 2019 17:50:49 +0200