持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第12天,点击查看活动详情
1、前言
每天一个算法小练习,本篇使用Java实现。
2、题目描述
给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。
- 1 <= nums.length <= 2500
- -104 <= nums[i] <= 104
2.1、示例1
输入:nums = [10,9,2,5,3,7,101,18]
输出:4
解释:最长递增子序列是 [2,3,7,101],因此长度为 4
2.2、示例2
输入:nums = [0,1,0,3,2,3]
输出:4
2.3、示例3
输入:nums = [7,7,7,7,7,7,7]
输出:1
3、解题思路
新建一个list,用来保存当前访问位置及之前位置对所有长度为i的子序列的最后一个元素值进行比较后的最小值。总之就是让list存储比较小的元素,最后list的长度就是最长子序列的长度。
3.1、贪心+二分查找
class Solution {
public int lengthOfLIS(int[] nums) {
List<Integer> resList = new ArrayList<>();
for(int i = 0; i < nums.length; i++){
if(resList.isEmpty() || nums[i] > resList.get(resList.size() - 1)){
//判断是否是较小的值,是则加入进来
resList.add(nums[i]);
}else{
//begin是在resList中第一个大于该数的下标
int begin = 0, end = resList.size() - 1, mid = 0;
//二分查找,遍历当前元素的前元素
while(begin <= end){
mid = (begin + end) >> 1;
if (resList.get(mid) < nums[i]){
begin = mid+1;
}else if(mid == 0|| resList.get(mid-1) < nums[i]){
break;
}else{
end = mid - 1;
}
}
//如果当前点的值大于前面的点,则更新
resList.set(mid, nums[i]);
}
}
return resList.size();
}
}
执行结果:
-
时间复杂度:,n为nums数组的长度,因为要遍历数组然后进行二分查找。
-
空间复杂度:。
好了、本期就先介绍到这里,有什么需要交流的,大家可以随时私信我。😊