
/**
动态规划O():
maxSubseq[]:记录结果,maxSubseq[i],代表以下标为i的元素结尾,最长递增子序列的长度
全部初始化为1,每个元素本身都是一个长度为1的子序列
以下标为0结尾:maxSubseq[0] = 1; 只有一个元素只能是1
以下标为1结尾:maxSubseq[1]---> if(nums[1] > nums[0]) ---> maxSubseq[0] + 1
以下标为2结尾:maxSubseq[2]---> if(nums[2] > nums[0,1]) ---> Math.max(maxSubseq[0,1] + 1 )
以下标为3结尾:maxSubseq[3]---> if(nums[3] > nums[0,1,2]) ---> Math.max(maxSubseq[0,1,2] + 1 )
.......
以下标为i结尾:maxSubseq[i]---> if(nums[i] > nums[0...i-1]) ---> Math.max(maxSubseq[0...i-1] + 1 )
即,比nums[i]小的元素(j)都进入待选,选择maxSubseq[j] + 1中最大的那个
二分查找+贪心:
维护一个List,遍历nums[],若nums[i] 大于List中的所有元素就将nums[i]插入到List的末尾
若不大于List中的所有元素,则在List中找到第一个小于等于nums[i]的元素进行替换
注意:
由于可能后出现的元素替换之前的元素,该方法只能保证找到最长子序列的长度,但最终List中不一定是最长子序列
*/
class Solution {
/**
动态规划O():
maxSubseq[]:记录结果,maxSubseq[i],代表以下标为i的元素结尾,最长递增子序列的长度
全部初始化为1,每个元素本身都是一个长度为1的子序列
以下标为0结尾:maxSubseq[0] = 1; 只有一个元素只能是1
以下标为1结尾:maxSubseq[1]---> if(nums[1] > nums[0]) ---> maxSubseq[0] + 1
以下标为2结尾:maxSubseq[2]---> if(nums[2] > nums[0,1]) ---> Math.max(maxSubseq[0,1] + 1 )
以下标为3结尾:maxSubseq[3]---> if(nums[3] > nums[0,1,2]) ---> Math.max(maxSubseq[0,1,2] + 1 )
.......
以下标为i结尾:maxSubseq[i]---> if(nums[i] > nums[0...i-1]) ---> Math.max(maxSubseq[0...i-1] + 1 )
即,比nums[i]小的元素(j)都进入待选,选择maxSubseq[j] + 1中最大的那个
二分查找+贪心:
维护一个List,遍历nums[],若nums[i] 大于List中的所有元素就将nums[i]插入到List的末尾
若不大于List中的所有元素,则在List中找到第一个小于等于nums[i]的元素进行替换
注意:
由于可能后出现的元素替换之前的元素,该方法只能保证找到最长子序列的长度,但最终List中不一定是最长子序列
*/
public int lengthOfLIS(int[] nums) {
//动态规划
//return DP(nums);
//二分查找+贪心
return GreedyBinarySearch(nums);
}
//动态规划
private int DP(int[] nums) {
int len = nums.length;
//maxSubseq[i],代表以下标为i的元素结尾,最长递增子序列的长度
int maxSubseq[] = new int[len];
//全部初始化为1,每个元素本身都是一个长度为1的子序列
Arrays.fill(maxSubseq,1);
//nums[i]小的元素(j)都进入待选,选择maxSubseq[j] + 1中最大的那个
int maxLen = 1; //记录最长子序列
for(int i = 0; i < len; i++) {
for(int j = 0; j < i; j++) {
if(nums[j] < nums[i]) {
maxSubseq[i] = Math.max(maxSubseq[i],maxSubseq[j] + 1); //过程中maxSubseq[i]中存储的是前[0,j - 1]最大的
}
}
maxLen = Math.max(maxLen,maxSubseq[i]); //迭代记录
}
return maxLen;
}
//二分查找+贪心
private int GreedyBinarySearch(int[] nums) {
//维护一个List,辅助记录最长子序列长度
List<Integer> tails = new ArrayList<>();
//二分查找寻找nums中元素应该的位置
for(int num : nums) {
int left = 0, right = tails.size() - 1;
//二分查找
while(left <= right) {
int mid = (left + right) / 2;
if(tails.get(mid) < num) {
left = mid + 1;
} else { //tails[mid] >= num 都向左半区搜索(找到第一个小于等于nums[i]的元素)
right = mid - 1;
}
}
//应该插入的位置就在最后
if(left == tails.size()) {
tails.add(num);
} else { //进行替换
tails.set(left,num);
}
}
return tails.size();
}
}

被折叠的 条评论
为什么被折叠?



