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)?
Violent solution: select all subsequences for judgment.
Dynamic planning:
Where "state" is defined: LIS(i) represents the length of the longest ascending subsequence ending with the ith number. That is, LIS(i) represents [0 In the range of, I], select the length of the longest ascending subsequence that can be obtained by nums[i].
According to the definition of state, determine the transfer of state:
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[0]; 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[1] = nums[0]; 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 } }