文章目录
动态规划之子序列连续问题
1.最长连续递增序列
1.1暴力解法
func findLengthOfLCIS(nums []int) int {
res := 1//连续子序列最少也是1
for i := 0; i < len(nums); i++ {
j := i
for j < len(nums)-1 && nums[j] < nums[j+1] {
j++
}
res = max(res, j-i+1)
}
return res
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
1.2贪心算法
func findLengthOfLCIS(nums []int) int {
res := 1
count := 0
for i := 0; i < len(nums)-1; i++ {
if nums[i+1] > nums[i] {
count++
} else {
count = 0
}
res =max(res,count+1)
}
return res
}
func max(a,b int)int{
if a >b{
return a
}
return b
}
//时间复杂度:O(n)
//空间复杂度:O(1)
1.3动态规划
func findLengthOfLCIS(nums []int) int {
n := len(nums)
dp := make([]int, n)
for i := 0; i < n; i++ {
dp[i] = 1
}
maxLength := 1
//从0开始方便计算,方便用上一次的值
for i := 1; i < n; i++ {
if nums[i] > nums[i-1] {
dp[i] = dp[i-1] + 1
}
maxLength =max(maxLength,dp[i])
}
return maxLength
}
func max(a,b int)int{
if a >b{
return a
}
return b
}
//O(n)
//空间复杂度:O(1)
2.最长重复子数组
2.1动态规划
func findLength(A []int, B []int) int {
m, n := len(A), len(B)
res := 0
dp := make([][]int, m+1)
for i := 0; i <= m; i++ {
dp[i] = make([]int, n+1)
}
//一行一行的进行遍历
for i := 1; i <= m; i++ {
for j := 1; j <= n; j++ {
if A[i-1] == B[j-1] {
//dp[i-1][j-1]在矩阵中是dp[i][j]的左上角元素
dp[i][j] = dp[i-1][j-1] + 1
}
res =max(dp[i][j],res)//res用于记录矩阵中最大的值
}
}
return res
}
func max(a,b int)int{
if a >b{
return a
}
return b
}
//时间复杂度:O(n × m),n 为A长度,m为B长度
//空间复杂度:O(n × m)
2.2滚动数组
func findLength(A []int, B []int) int {
n, m := len(A), len(B)
ret := 0//用于记录最大值
for i := 0; i < n; i++ {
len := min(m, n - i)
maxLen := maxLength(A, B, i, 0, len)
ret = max(ret, maxLen)
}
for i := 0; i < m; i++ {
len := min(n, m - i)
maxLen := maxLength(A, B, 0, i, len)
ret = max(ret, maxLen)
}
return ret
}
func maxLength(A, B []int, addA, addB, len int) int {
ret, k := 0, 0
for i := 0; i < len; i++ {
if A[addA + i] == B[addB + i] {
k++
} else {
k = 0
}
ret = max(ret, k)
}
return ret
}
func max(x, y int) int {
if x > y {
return x
}
return y
}
func min(x, y int) int {
if x < y {
return x
}
return y
}
//时间复杂度: O((N+M)×min(N,M)) N 表示数组 A 的长度,M 表示数组 B 的长度
//空间复杂度: O(1)
3.最大子数组和(最大子序和)
3.1暴力求解
func maxSubArray(nums []int) int {
result := math.MinInt32
for i := 0; i < len(nums); i++ {
count := 0
for j := i; j < len(nums); j++ {
count += nums[j]
if count > result {
result = count
} else {
continue
}
}
}
return result
}
//时间复杂度:O(n^2)
//空间复杂度:O(1)
3.2贪心算法
func maxSubArray(nums []int) int {
//不能写成 result := -1
result := math.MinInt32//写成这的原因是为了方便使数组的第一个数如果是负数的话也可以照常被赋值
count := 0//每一次序列的开始,及序列的不断累加
for i := 0; i < len(nums); i++ {
count += nums[i]
//resuly只会不断地的增加
if count >result {
result =count
}
if count <= 0 {
count = 0
}
}
return result
}
//[-1,-2,-3]的输出结果是-1
//时间复杂度:O(n)
//空间复杂度:O(1)
3.3动态规划
func main() {
a := []int{5, 4, -1, 7, 8}
fmt.Println(a) //输出:[5 4 -1 7 8]
fmt.Println(maxSubArray(a)) //输出:23
fmt.Println(a) //输出:[5 9 8 15 23]
}
func maxSubArray(nums []int) int {
n := len(nums)
// 这里的dp[i] 表示,最大的连续子数组和,包含num[i] 元素
dp := make([]int,n)
// 初始化,由于dp 状态转移方程依赖dp[0]
dp[0] = nums[0]
// 初始化最大的和
mx := nums[0]
for i:=1;i<n;i++ {
// 这里的状态转移方程就是:求最大和
// 会面临2种情况,一个是带前面的和,一个是不带前面的和
dp[i] = max(dp[i-1]+nums[i],nums[i])
mx = max(mx,dp[i])
}
return mx
}
func max(a,b int) int{
if a>b {
return a
}
return b
}
//思想:动态规划
//时间复杂度:O(n)
//空间复杂度:O(n)