Given an unsorted array of integers, find the length of longest increasing subsequence.
Example:
Input: [10,9,2,5,3,7,101,18]Output: 4Explanation: The longest increasing subsequence is [2,3,7,101], therefore the length is 4.
Note:
- There may be more than one LIS combination, it is only necessary for you to return the length.
- Your algorithm should run in O(
) complexity.
Follow up: Could you improve it to O(n log n) time complexity?
题意
找到一个无序数组中的最长递增子序列。
思路
- 暴力法,直接使用dfs搜索;
- 对暴力法进行优化,将每一次dfs的结果记录下来;
- 动态规划。dp[i]代表以nums[i]为结尾的最长递增子数列的长度。针对一个i,遍历 j (j = 0, 1, …, i - 1),如果nums[i]>nums[j],说明可以将nums[i]添加到nums[j]后面构成一个新的递增子数列,其长度为dp[j]+1,这时候更新dp[i]为dp[i]和dp[j]+1之中较大的一个即可;
- 动态规划二分优化。遍历nums数组,针对每一个nums[i],用二分法查找它在dp数组中应该出现的位置x,如果该位置上已经有数,则更新dp[x]=nums[i];如果该位置上还没有数,则将nums[i]插入到该位置。
代码实现 - dfs暴力
class Solution {public int lengthOfLIS(int[] nums) {return dfs(nums, -1, 0);}private int dfs(int[] nums, int pre, int cur) {if (cur == nums.length) {return 0;}int use = (pre < 0 || nums[cur] > nums[pre]) ? 1 + dfs(nums, cur, cur + 1) : 0;int skip = dfs(nums, pre, cur + 1);return Math.max(use, skip);}}
代码实现 - dfs优化
class Solution {public int lengthOfLIS(int[] nums) {int[][] memo = new int[nums.length][nums.length];for (int[] list : memo) {Arrays.fill(list, -1);}return dfs(nums, -1, 0, memo);}private int dfs(int[] nums, int pre, int cur, int[][] memo) {if (cur == nums.length) {return 0;}if (memo[pre + 1][cur] >= 0) {return memo[pre + 1][cur];}int use = (pre < 0 || nums[cur] > nums[pre]) ? 1 + dfs(nums, cur, cur + 1, memo) : 0;int skip = dfs(nums, pre, cur + 1, memo);memo[pre + 1][cur] = Math.max(use, skip);return memo[pre + 1][cur];}}
代码实现 - 动态规划
class Solution {public int lengthOfLIS(int[] nums) {int[] dp = new int[nums.length];int maxLen = 0;for (int i = 0; i < nums.length; i++) {dp[i] = 1; // 初始值为1for (int j = 0; j < i; j++) {dp[i] = nums[i] > nums[j] ? Math.max(dp[i], dp[j] + 1) : dp[i];}maxLen = Math.max(maxLen, dp[i]);}return maxLen;}}
代码实现 - 动态规划二分优化
class Solution {public int lengthOfLIS(int[] nums) {List<Integer> dp = new ArrayList<>();for (int i = 0; i < nums.length; i++) {int pos = binarySearch(dp, nums[i]);if (pos == dp.size()) {dp.add(nums[i]);} else {dp.set(pos, nums[i]);}}return dp.size();}private int binarySearch(List<Integer> list, int target) {int left = 0, right = list.size() - 1;while (left <= right) {int mid = left + (right - left) / 2;if (list.get(mid) < target) {left = mid + 1;} else if (list.get(mid) > target) {right = mid - 1;} else {return mid;}}return left;}}
