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

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

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)暂停更


目录
相关文章
|
2月前
|
Java 虚拟化 容器
(Java)Java里JFrame窗体的基本操作(容器布局篇-1)
容器 容器,我的理解是可以包容其他东西的玩意。它可以是一个盒子,可以是一个虚拟化的物品,可只要能包裹住其他存在质体的东西,那么都可以称作是容器。例如:JPanel组件和JScollPane组件两者都是容器也是组件。 既然有容器,那么容器中的布局就必不可少了。不然不规矩的摆放物品,人类看不习惯,我也看不习惯 ???? 本篇内容,将说明java JFrame窗体里容器中几类布局。 说明:所有在JFrame窗体里的容器布局都会使用setLayout()方法,采用的布局参数都将放进这个方法里 绝对布局 调用窗体容器
96 1
|
6月前
|
存储 缓存 安全
Java 集合容器常见面试题及详细解析
本文全面解析Java集合框架,涵盖基础概念、常见接口与类的特点及区别、底层数据结构、线程安全等内容。通过实例讲解List(如ArrayList、LinkedList)、Set(如HashSet、TreeSet)、Map(如HashMap、TreeMap)等核心组件,帮助读者深入理解集合容器的使用场景与性能优化。适合准备面试或提升开发技能的开发者阅读。
107 0
|
6月前
|
缓存 Java API
Java 集合容器实操技巧与案例详解
本教程基于Java 8+新特性和现代开发实践,深入讲解Java集合容器的实操技巧。通过具体场景演示Stream API数据处理、ConcurrentHashMap并发控制、LinkedHashMap实现LRU缓存、TreeSet自定义排序等高级特性。同时涵盖computeIfAbsent优化操作、EnumMap专用集合使用、集合统计与运算(交集、并集、差集)等内容。代码示例丰富,助力掌握高效编程方法。[点击获取完整代码](https://pan.quark.cn/s/14fcf913bae6)。
81 0
|
Kubernetes Cloud Native Java
云原生之旅:从容器到微服务的演进之路Java 内存管理:垃圾收集器与性能调优
【8月更文挑战第30天】在数字化时代的浪潮中,企业如何乘风破浪?云原生技术提供了一个强有力的桨。本文将带你从容器技术的基石出发,探索微服务架构的奥秘,最终实现在云端自由翱翔的梦想。我们将一起见证代码如何转化为业务的翅膀,让你的应用在云海中高飞。
|
10月前
|
存储 安全 算法
Java容器及其常用方法汇总
Java Collections框架提供了丰富的接口和实现类,用于管理和操作集合数据。
169 2
Java容器及其常用方法汇总
|
Java Linux Maven
java依赖冲突解决问题之容器加载依赖jar包如何解决
java依赖冲突解决问题之容器加载依赖jar包如何解决
|
11月前
|
监控 Java 中间件
8G的容器Java堆才4G怎么就OOM了?
本文记录最近一例Java应用OOM问题的排查过程,希望可以给遇到类似问题的同学提供参考。
|
存储 安全 Java
Java多线程编程中的并发容器:深入解析与实战应用####
在本文中,我们将探讨Java多线程编程中的一个核心话题——并发容器。不同于传统单一线程环境下的数据结构,并发容器专为多线程场景设计,确保数据访问的线程安全性和高效性。我们将从基础概念出发,逐步深入到`java.util.concurrent`包下的核心并发容器实现,如`ConcurrentHashMap`、`CopyOnWriteArrayList`以及`BlockingQueue`等,通过实例代码演示其使用方法,并分析它们背后的设计原理与适用场景。无论你是Java并发编程的初学者还是希望深化理解的开发者,本文都将为你提供有价值的见解与实践指导。 --- ####
|
消息中间件 NoSQL Kafka
Flink-10 Flink Java 3分钟上手 Docker容器化部署 JobManager TaskManager Kafka Redis Dockerfile docker-compose
Flink-10 Flink Java 3分钟上手 Docker容器化部署 JobManager TaskManager Kafka Redis Dockerfile docker-compose
357 4
|
Kubernetes Cloud Native 流计算
Flink-12 Flink Java 3分钟上手 Kubernetes云原生下的Flink集群 Rancher Stateful Set yaml详细 扩容缩容部署 Docker容器编排
Flink-12 Flink Java 3分钟上手 Kubernetes云原生下的Flink集群 Rancher Stateful Set yaml详细 扩容缩容部署 Docker容器编排
361 3

热门文章

最新文章

推荐镜像

更多