LIS
Given an integer array nums, return the length of the longest strictly increasing subsequence.
动态规划 复杂度 \(O(n^2)\)
class Solution {
fun lengthOfLIS(nums: IntArray): Int {
// dp[i] 表示前 i + 1 个数的最大上升子序列个数
val dp = IntArray(nums.size) { 1 }
for (i in nums.indices) {
var max = 1
for (j in 0 until i) {
if (nums[j] < nums[i]) max = max.coerceAtLeast(dp[j] + 1)
}
dp[i] = max
}
return dp.max()
}
}
贪心 + 二分查找 复杂度 \(O(n\log{n})\)
class Solution {
fun lengthOfLIS(nums: IntArray): Int {
val sub = IntArray(nums.size)
var length = 0
for (n in nums) {
var index = sub.binarySearch(n, 0, length)
if (index < 0) index = -(index + 1)
sub[index] = n
if (index == length) length++
}
return length
}
}
动态规划 + 树状数组 复杂度 \(O(n\log{n})\)
方案一:
class BIT(size: Int) {
private val bit = IntArray(size + 1)
fun get(index: Int): Int {
var max = 0
var i = index
while (i > 0) {
max = max.coerceAtLeast(bit[i])
i -= i.and(-i)
}
return max
}
fun update(index: Int, value: Int) {
var i = index
while (i < bit.size) {
bit[i] = bit[i].coerceAtLeast(value)
i += i.and(-i)
}
}
}
class Solution {
fun lengthOfLIS(nums: IntArray): Int {
val bit = BIT(nums.size)
nums.mapIndexed { i, n ->
Pair(i + 1, n)
}.sortedWith { (i1, n1), (i2, n2) ->
if (n1 == n2) i2 - i1 else n1 - n2
}.forEach { (index, num) ->
var max = bit.get(index - 1)
bit.update(index, ++max)
}
return bit.get(nums.size)
}
}
方案二:
class BIT(size: Int) {
private val bit = IntArray(size + 1)
fun get(index: Int): Int {
var max = 0
var i = index
while (i > 0) {
max = max.coerceAtLeast(bit[i])
i -= i.and(-i)
}
return max
}
fun update(index: Int, value: Int) {
var i = index
while (i < bit.size) {
bit[i] = bit[i].coerceAtLeast(value)
i += i.and(-i)
}
}
}
class Solution {
fun lengthOfLIS(nums: IntArray): Int {
val min = nums.min()
val max = nums.max()
val bit = BIT(max - min + 1)
for (n in nums) {
bit.update(n - min + 1, bit.get(n - min) + 1)
}
return bit.get(max - min + 1)
}
}
求 LIS 个数
// todo
求 LIS 具体序列
// todo