Golang每日一练(leetDay0101) 最长递增子序列I\II\个数

目录

300. 最长递增子序列 Longest Increasing Subsequence  

2407. 最长递增子序列 II Longest Increasing Subsequence ii  

673. 最长递增子序列的个数 Number of Longest Increasing Subsequence  

每日一练刷题专栏 

Rust每日一练 专栏

Golang每日一练 专栏

Python每日一练 专栏

C/C++每日一练 专栏

Java每日一练 专栏


300. 最长递增子序列 Longest Increasing Subsequence

给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。

子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。

示例 1:

输入:nums = [10,9,2,5,3,7,101,18]
输出:4
解释:最长递增子序列是 [2,3,7,101],因此长度为 4 。

示例 2:

输入:nums = [0,1,0,3,2,3]
输出:4

示例 3:

输入:nums = [7,7,7,7,7,7,7]
输出:1

提示:

  • 1 <= nums.length <= 2500
  • -10^4 <= nums[i] <= 10^4

进阶:

  • 你能将算法的时间复杂度降低到 O(n log(n)) 吗?

代码1:二分查找,时间复杂度 O(n log n)

package main

import "fmt"

func lengthOfLIS(nums []int) int {
	n := len(nums)
	if n == 0 {
		return 0
	}
	d := make([]int, n+1)
	d[1] = nums[0]
	len := 1
	for i := 1; i < n; i++ {
		if nums[i] > d[len] {
			len++
			d[len] = nums[i]
		} else {
			l, r := 1, len
			pos := 0
			for l <= r {
				mid := l + (r-l)/2
				if d[mid] < nums[i] {
					pos = mid
					l = mid + 1
				} else {
					r = mid - 1
				}
			}
			d[pos+1] = nums[i]
		}
	}
	return len
}

func main() {
	nums := []int{10, 9, 2, 5, 3, 7, 101, 18}
	fmt.Println(lengthOfLIS(nums))

	nums = []int{0, 1, 0, 3, 2, 3}
	fmt.Println(lengthOfLIS(nums))

	nums = []int{7, 7, 7, 7, 7, 7, 7}
	fmt.Println(lengthOfLIS(nums))
}

输出:

4
4
1

代码2:动态规划,时间复杂度:O(n^2)

package main

import "fmt"

func lengthOfLIS(nums []int) int {
    n := len(nums)
    dp := make([]int, n)
    // 初始化 dp 数组
    for i := 0; i < n; i++ {
        dp[i] = 1
    }
    ans := 1
    // 开始 dp
    for i := 1; i < n; i++ {
        for j := 0; j < i; j++ {
            if nums[j] < nums[i] {
                dp[i] = max(dp[i], dp[j]+1)
            }
        }
        ans = max(ans, dp[i])
    }
    return ans
}

func max(x, y int) int {
    if x > y {
        return x
    }
    return y
}

func main() {
	nums := []int{10, 9, 2, 5, 3, 7, 101, 18}
	fmt.Println(lengthOfLIS(nums))

	nums = []int{0, 1, 0, 3, 2, 3}
	fmt.Println(lengthOfLIS(nums))

	nums = []int{7, 7, 7, 7, 7, 7, 7}
	fmt.Println(lengthOfLIS(nums))
}

2407. 最长递增子序列 II Longest Increasing Subsequence ii

给你一个整数数组 nums 和一个整数 k 。

找到 nums 中满足以下要求的最长子序列:

  • 子序列 严格递增
  • 子序列中相邻元素的差值 不超过 k 。

请你返回满足上述要求的 最长子序列 的长度。

子序列 是从一个数组中删除部分元素后,剩余元素不改变顺序得到的数组。

示例 1:

输入:nums = [4,2,1,4,3,4,5,8,15], k = 3
输出:5
解释:
满足要求的最长子序列是 [1,3,4,5,8] 。
子序列长度为 5 ,所以我们返回 5 。
注意子序列 [1,3,4,5,8,15] 不满足要求,因为 15 - 8 = 7 大于 3 。

示例 2:

输入:nums = [7,4,5,1,8,12,4,7], k = 5
输出:4
解释:
满足要求的最长子序列是 [4,5,8,12] 。
子序列长度为 4 ,所以我们返回 4 。

示例 3:

输入:nums = [1,5], k = 1
输出:1
解释:
满足要求的最长子序列是 [1] 。
子序列长度为 1 ,所以我们返回 1 。

提示:

  • 1 <= nums.length <= 10^5
  • 1 <= nums[i], k <= 10^5

代码:二分查找

package main

import "fmt"

var mx []int // 全局变量

func updateTree(root, l, r, i, val int) {
	if l == r {
		mx[root] = val
		return
	}
	mid := (l + r) / 2
	if i <= mid {
		updateTree(root*2, l, mid, i, val)
	} else {
		updateTree(root*2+1, mid+1, r, i, val)
	}
	mx[root] = max(mx[root*2], mx[root*2+1])
}

func query(root, l, r, L, R int) int {
	if L <= l && r <= R {
		return mx[root]
	}
	ret := 0
	mid := (l + r) / 2
	if L <= mid {
		ret = query(root*2, l, mid, L, R)
	}
	if R > mid {
		ret = max(query(root*2+1, mid+1, r, L, R), ret)
	}
	return ret
}

func lengthOfLIS(nums []int, k int) int {
	up := 0
	for _, x := range nums {
		if x > up {
			up = x
		}
	}
	mx = make([]int, 4*up)
	for _, x := range nums {
		if x == 1 {
			updateTree(1, 1, up, 1, 1)
		} else {
			L := x - k
			if L < 1 {
				L = 1
			}
			ret := 1 + query(1, 1, up, L, x-1)
			updateTree(1, 1, up, x, ret)
		}
	}
	return mx[1]
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func main() {
	nums1 := []int{4, 2, 1, 4, 3, 4, 5, 8, 15}
	k1 := 3
	fmt.Println(lengthOfLIS(nums1, k1))
	nums2 := []int{7, 4, 5, 1, 8, 12, 4, 7}
	k2 := 5
	fmt.Println(lengthOfLIS(nums2, k2))
	nums3 := []int{1, 5}
	k3 := 1
	fmt.Println(lengthOfLIS(nums3, k3))
}

输出:

5
4
1


673. 最长递增子序列的个数 Number of Longest Increasing Subsequence

给定一个未排序的整数数组 nums , 返回最长递增子序列的个数 。

注意 这个数列必须是 严格 递增的。

示例 1:

输入: [1,3,5,4,7]
输出: 2
解释: 有两个最长递增子序列,分别是 [1, 3, 4, 7] 和[1, 3, 5, 7]。

示例 2:

输入: [2,2,2,2,2]
输出: 5
解释: 最长递增子序列的长度是1,并且存在5个子序列的长度为1,因此输出5。

提示: 

  • 1 <= nums.length <= 2000
  • -10^6 <= nums[i] <= 10^6

代码:

package main

import "fmt"

func findNumberOfLIS(nums []int) int {
	n := len(nums)
	if n <= 1 {
		return n
	}
	dp := make([]int, n)
	cnt := make([]int, n)
	for i := range dp {
		dp[i], cnt[i] = 1, 1
	}
	maxLen, ans := 1, 0
	for i := 1; i < n; i++ {
		for j := 0; j < i; j++ {
			if nums[j] < nums[i] {
				if dp[j]+1 > dp[i] {
					dp[i], cnt[i] = dp[j]+1, cnt[j]
				} else if dp[j]+1 == dp[i] {
					cnt[i] += cnt[j]
				}
			}
		}
		maxLen = max(maxLen, dp[i])
	}
	for i := range cnt {
		if dp[i] == maxLen {
			ans += cnt[i]
		}
	}
	return ans
}

func max(x, y int) int {
	if x > y {
		return x
	}
	return y
}

func main() {
	fmt.Println(findNumberOfLIS([]int{1, 3, 5, 4, 7}))
	fmt.Println(findNumberOfLIS([]int{2, 2, 2, 2, 2}))
}

输出:

2
5


每日一练刷题专栏 

持续,努力奋斗做强刷题搬运工!

点赞,你的认可是我坚持的动力! 

 收藏,你的青睐是我努力的方向! 

评论,你的意见是我进步的财富!  

 主页:https://hannyang.blog.csdn.net/ 

Rust每日一练 专栏

(2023.5.16~)更新中...

Golang每日一练 专栏

(2023.3.11~)更新中...

Python每日一练 专栏

(2023.2.18~2023.5.18)暂停更

C/C++每日一练 专栏

(2023.2.18~2023.5.18)暂停更

Java每日一练 专栏

(2023.3.11~2023.5.18)暂停更

你可能感兴趣的:(#,Go,Leetcode,刷题专栏,golang,leetcode)