描述
给定数组 arr ,设长度为 n ,输出 arr 的最长上升子序列。(如果有多个答案,请输出其中 按数值(注:区别于按单个字符的ASCII码值)进行比较的 字典序最小的那个)
输入:
[2,1,5,3,6,4,8,9,7]
返回值:
[1,3,4,8,9]
package main
import "sort"
/**
* retrun the longest increasing subsequence
* @param arr int整型一维数组 the array
* @return int整型一维数组
*/
func LIS( arr []int ) []int {
// write code here
if len(arr) == 0 { return nil }
n := len(arr)
var lis,dp = make([]int,0),make([]int,n)
lis = append(lis,arr[0])
dp[0] = 1 //即第一个元素结尾时的递增数组长度
for i:=1;i<n;i++ {
if arr[i] > lis[len(lis)-1] {
lis = append(lis,arr[i])
dp[i] = len(lis)
}else {
// 小于 , 替换前面的
x := arr[i]
var first = sort.Search(len(lis),func (i int) bool {
return lis[i] >= x
})
lis[first ] = x
dp[i] = first+ 1
}
}
// 里要求返回字典顺序最小的,我们可以分析下dp[i]的长度变化
//仅当arr[i]<=arr[j]时(其中i>j),dp[i]是不会变化,取的值是0~i-1之间的最大长度
// 例如
// arr = [1 2 8 6 4]
// dp = [1 2 3 3 3]
// lis = [1 2 4], maxlen=3
// 可见,字典顺序就是[1 2 4],按照逆序处理,遍历dp数组,第一个变化的值就是最小的字典序
mx := len(lis)
res := make([]int,mx)
for i:=n-1;i>=0;i-- {
if dp[i] == mx {
mx--
res[mx] = arr[i]
}
}
return res
}