1.最长上升子序列
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class LengthOfLIS {
/**
* Created with IntelliJ IDEA.
* Description:
* User:
* Date: 2020-11-12
* Time: 21:26
*/
public static void main(String[] args) {
ArrayList<Integer> inte = new ArrayList<Integer>();
inte.add(1);
inte.add(2);
inte.add(3);
inte.add(4);
inte.add(5);
inte.add(6);
inte.add(8);
inte.forEach(System.out::println);
//(-(插入点) - 1)。插入点 被定义为将键插入列表的那一点:即第一个大于此键的元素索引
System.out.println(Collections.binarySearch(inte, 7));
}
public static int lengthOfLIS(int[] nums) {
//首先边界条件的确定
if (nums.length <= 0) {
return 0;
}
//考虑就一个数组用来存放状态值,对数组的余地,dp[i] = number 第多少个数的最长上升子序列
int[] dp = new int[nums.length];
//考虑最小的长度为一,初始化数组
Arrays.fill(dp, 1);
//怎么确定转移方程,既是我们知道dp[i-1] 怎么求dp[i]
//我们只要找到前面的子问题中最后一位比dp[i]小的最大子问题即可+1
//使用一个循环求取所有的状态
for (int i = 0; i < nums.length; i++) {
for (int j = 0; j < i; j++) {
//这里的判断是求取的关键
if (nums[i] > nums[j]) {
dp[i] = Math.max(dp[i], dp[j] + 1);
}
}
}
//数组中最大的状态就是最长的最长上升子序列
int tmp = 0;
for (int i = 0; i < nums.length; i++) {
tmp = Math.max(dp[i], tmp);
}
return tmp;
}
public static int lengthOfLIS1(int[] nums) {
//使用二分查找
//思路建立一个集合,首先存储第一次的数,以及如果某前面的数小于后面的数直接添加到集合中
List<Integer> list = new ArrayList<>(nums.length);
for (int num : nums) {
//集合的长度为0的时候或者前面的数小于后面的数就添加到集合中
if (list.size() == 0 || list.get(list.size() - 1) < num) {
list.add(num);
} else {
//二分法 binarySearch返回值是第一个大于它的索引
// (-(插入点) - 1)。插入点 被定义为将键插入列表的那一点:即第一个大于此键的元素索引
int i = Collections.binarySearch(list, num);
//如果i>0 说明本来就存在直接替换即可 ,如果小于取反减去1
list.set((i < 0) ? -i-1 : i , num);
//下面的这种写法通过不了
// list.set((i > 0) ? i : -i - 1, num);
}
}
return list.size();
}
}
网友评论