leetcode 300. 最长上升子序列
- O(N^2)解法,动态规划
func lengthOfLIS(nums []int) int {
n := len(nums)
if n == 0 {
return 0
}
ret := 1
dp := make([]int, n)
dp[0] = 1
// dp[i]表示,包括i这个数的数组,最大
for i := 1; i < n; i++ {
// 初始值都为1
dp[i] = 1
for j := 0; j < i; j++ {
// 如果当前数字大于那个位置的数字,那么显然算上当前数字,序列会加1
// 比那个位置小或者等于那个位置的情况,在之前或者之后的j得到处理(即和每个j都比较了)
// dp[i] 取之前的所有dp[j]中的最大值加1
if nums[i] > nums[j] {
dp[i] = max(dp[i], dp[j]+1)
}
}
ret = max(ret, dp[i])
}
return ret
}
- O(NlogN),第二层循环用二分法替换
func lengthOfLIS(nums []int) int {
n := len(nums)
if n == 0 {
return 0
}
// 维护最长子序列数组
list := []int{nums[0]}
var l, r, mid int
for i := 1; i < n; i++ {
l, r = 0, len(list)-1
// 二分 注意是小于等于,因为还要判断最后一个数字
for l <= r {
mid = (l + r) / 2
if list[mid] >= nums[i] {
r -= 1
}else {
l += 1
}
}
// 说明list中数字都小
if mid == r {
list = append(list, nums[i])
} else { // 说明有比他大的,第一个就是mid
list[mid] = nums[i]
}
}
return len(list)
}
来源:CSDN
作者:KeyboardMan6
链接:https://blog.csdn.net/weixin_40108561/article/details/104226263