Golang递增子序列系列问题

一共包括三个子问题
实现语言问golang,在二分法中用到了sort包里的SearchInts
最长连续递增子序列

func continuouslengthOfLIS(nums []int) int {
	//最长的连续递增子序列长度
	ans, left := 1, 0
	for i := 1; i < len(nums); i++ {
		if nums[i] <= nums[i-1] {
			ans = max(ans, i-left)
			left = i
		}
	}
	ans = max(ans, len(nums)-left)
	return ans
}

最长递增子序列的长度
时间复杂度为n²

func dplengthOfLIS(nums []int) int {
	//返回最长递增子序列的长度
	ans := 0
	n := len(nums)
	dp := make([]int, n)
	//dp[i]表示前i个数组成的最长子序列长度
	for i := 0; i < n; i++ {
		//子序列长度最少为1
		dp[i] = 1
		for j := 0; j < i; j++ {
			if nums[i] > nums[j] {
				//如果i大于j对应的数,那么第j个数对应的最长子序列就可以加上第i个数,长度+1
				dp[i] = max(dp[i], dp[j]+1)
				//记录最大的dp值
				ans = max(ans, dp[i])
			}
		}
	}
	return ans
}

使用二分法
时间复杂度为n * log(n)

func binarysearchlengthOfLIS(nums []int) int {
	//采用二分法和贪心策略
	//基本思想就是尽量让数组的尾部小,这样就可以添进来更多数
	//例如1 100 2 10 20 3 4 30 170 150
	//1
	//1 100
	//1 2
	//1 2 10
	//1 2 10 20
	//1 2 3 20
	//1 2 3 4
	//1 2 3 4 30
	//1 2 3 4 30 170
	//1 2 3 4 30 150
	ans := []int{}
	ans = append(ans, nums[0])
	for i := 1; i < len(nums); i++ {
		//遍历nums数组
		if nums[i] > ans[len(ans)-1] {
			//如果第i个数比ans数组的末尾元素大,就添加进去
			ans = append(ans, nums[i])
		} else if nums[i] < ans[len(ans)-1] {
			//如果第i个数比ans数组的末尾元素小,就一直往前寻找,直到找到第一个比他大的数,替换掉
			index := sort.SearchInts(ans, nums[i])
			ans[index] = nums[i]
		}
	}
	return len(ans)
}

最长递增子序列的个数

func numOflengthOfLIS(nums []int) int {
	//返回最长子序列对应的个数
	ans := 1
	// ans记录最长的长度
	n := len(nums)
	//dp 记录前i个数的最长子序列的长度
	dp := make([]int, n)
	//count 记录前i个数的最长子序列长度的个数
	count := make([]int, n)
	//dp[i]表示前i个数组成的最长子序列长度
	for i := 0; i < n; i++ {
		//子序列长度最少为1
		dp[i] = 1
		count[i] = 1
		for j := 0; j < i; j++ {
			if nums[i] > nums[j] {
				//如果i大于j对应的数,那么第j个数对应的最长子序列就可以加上第i个数,长度+1
				if dp[j]+1 > dp[i] {
					//如果前j个数的最长子序列长度+1比当前前i个数的最长子序列长度长,那就更新当前的长度,且排列方式数量等于前j个的排列方式
					dp[i] = dp[j] + 1
					count[i] = count[j]
				} else if dp[j]+1 == dp[i] {
					//如果前j个数的最长子序列长度+1和当前前i个数的最长子序列长度一样,那这个长度的方式就再加上前j个的排列方式
					count[i] += count[j]
				}
				//还有另一种情况就是前j个的长度+1,还没有现在的长,那就抛弃不用

				//记录最大的dp值
				ans = max(ans, dp[i])
			}
		}
	}
	if ans == 1 {
		return n
	}
	ret := 0
	for i := range dp {
		if dp[i] == ans {
			ret += count[i]
		}
	}
	return ret
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LSY_HELLOWORLD

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值