题目描述:具体描述见原题。简单来说就是求最长上升子序列长度。
解题思路:该题存在两种解题思路。第一种是直接考虑dp,dp[i]代表以nums[i]为结尾的字长上升子序列长度,则可得状态转移方程为dp[i] = max(dp[j] + 1)。其中j < i。因为两层循环所以时间复杂度为O。第二种思路是我抄来的,用一个数组,记录上升子序列最末尾的数字,如果该数字越小,那么后续该子序列增长的概率越大,此种思路更新策略为如果当前处理数字大于所有数组中元素,那么就直接放在末尾,如果当前数字大于[i-1]且小于[i],则更新数组[i]的值,最终该数组长度记为最长上升子序列长度,该方法时间复杂度为O。具体过程见代码。
具体代码:
// 直接dp
func lengthOfLIS(nums []int) int {
if len(nums) == 0 {
return 0
}
dp, res := make([]int, len(nums)), 0
for i, _ := range dp{
dp[i] = 1
}
for i := 0; i < len(nums); i++ {
for j := 0; j < i; j++ {
if nums[j] >= nums[i] {
continue
}
if dp[i] < dp[j] + 1 {
dp[i] = dp[j] + 1
}
}
if res < dp[i] {
res = dp[i]
}
}
return res
}
// 使用数组记录
func lengthOfLIS(nums []int) int {
dp := []int{}
for _, num := range nums {
i := sort.SearchInts(dp, num)
if i == len(dp) {
dp = append(dp, num)
} else {
dp[i] = num
}
}
return len(dp)
}
补充说明: 两种解法在解题时间上还是有明显差距的。解法二真是好用,不知道是谁最先想出来的。