今日任务:
资料来源:
题目
子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[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
提示:
进阶:
你能将算法的时间复杂度降低到 O(n log(n)) 吗?
这题还是,循环尝试选取每个元素。对于每个元素来说,要么就是比之前的元素要大,要选上;要么就是不比之前的元素大,重新开始选这两种状态,递推公式这就有了。
gofunc lengthOfLIS(nums []int) int {
dpArray := make([]int, len(nums))
for i := range dpArray { // 初始化 因为每个数字自己就是一个递增子序列
dpArray[i] = 1
}
maxValue := 1
for i := 1; i < len(nums); i++ {
for j := i - 1; j >= 0; j-- { // 这题不要求连续 所以要把之前选过的元素都循环一次看看连得上连不上
if nums[j] < nums[i] {
dpArray[i] = max(dpArray[i], dpArray[j] + 1) // 递推公式
}
}
if dpArray[i] > maxValue {
maxValue = dpArray[i]
}
}
return maxValue
}
题目
给定一个未经排序的整数数组,找到最长且 连续递增的子序列,并返回该序列的长度。
连续递增的子序列 可以由两个下标 l 和 r(l < r)确定,如果对于每个 l <= i < r,都有 nums[i] < nums[i + 1] ,那么子序列 [nums[l], nums[l + 1], ..., nums[r - 1], nums[r]] 就是连续递增子序列。
示例 1:
输入:nums = [1,3,5,4,7] 输出:3 解释:最长连续递增序列是 [1,3,5], 长度为3。 尽管 [1,3,5,7] 也是升序的子序列, 但它不是连续的,因为 5 和 7 在原数组里被 4 隔开。
示例 2:
输入:nums = [2,2,2,2,2] 输出:1 解释:最长连续递增序列是 [2], 长度为1。
提示:
这题和上一个题差不多,甚至还更简单一点。上一题由于子序列可以不连续,所以需要两层循环,内层循环查之前的元素能否连上。这次一层循环就够用了,只查nums[i - 1]
就行了。
gofunc findLengthOfLCIS(nums []int) int {
dpArray := make([]int, len(nums))
for i := range dpArray {
dpArray[i] = 1
}
result := 1
for i := 1; i < len(nums); i++ {
if nums[i] > nums[i - 1] {
dpArray[i] = dpArray[i - 1] + 1
}
if dpArray[i] > result {
result = dpArray[i]
}
}
return result
}
题目
给两个整数数组 nums1 和 nums2 ,返回 两个数组中 公共的 、长度最长的子数组的长度 。
示例 1:
输入:nums1 = [1,2,3,2,1], nums2 = [3,2,1,4,7] 输出:3 解释:长度最长的公共子数组是 [3,2,1] 。
示例 2:
输入:nums1 = [0,0,0,0,0], nums2 = [0,0,0,0,0] 输出:5
提示:
这题需要用二维数组,两个维度分别对应两个数组,这样才能所有元素都匹配一次。对于dpArray[j][i]
来说,如果nums1[i] == nums2[j]
成立,说明找到了一个相同元素,从dpArray[j - 1][i - 1]
进行状态推导(因为是连续的,如果要选上这个元素,两个数组得一起选)。
另外,参照01背包问题,这题可以状态压缩为一维数组。
gofunc findLength(nums1 []int, nums2 []int) int {
dpArray := make([][]int, len(nums2))
for i := range dpArray {
dpArray[i] = make([]int, len(nums1))
}
result := 0
// 初始化 这个初始化方法也和01背包有点像的
for i := 0; i < len(nums1); i++ {
if nums1[i] == nums2[0] {
dpArray[0][i] = 1
result = 1
}
}
for i := 0; i < len(nums2); i++ {
if nums1[0] == nums2[i] {
dpArray[i][0] = 1
result = 1
}
}
// 开始推导
for i := 1; i < len(nums1); i++ {
for j := 1; j < len(nums2); j++ {
if nums1[i] == nums2[j] {
dpArray[j][i] = dpArray[j - 1][i - 1] + 1
if dpArray[j][i] > result {
result = dpArray[j][i]
}
}
}
}
return result
}
本文作者:御坂19327号
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!