动态规划习题(二)

左心房为你撑大大i 提交于 2020-02-08 19:10:36

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)
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!