题目
'''
Description: 300.最长递增子序列
Autor: 365JHWZGo
Date: 2021-12-14 10:35:10
LastEditors: 365JHWZGo
LastEditTime: 2021-12-14 15:43:52
'''
思路
子序列(subsequence)
a sequence that can be derived from an array by deleting some or no elements without changing the order of the remaining elements.
意思就是在保持原来的数组顺序不变的情况下删除多个或不删除元素。
直观解题思路:
找到它在之前序列中的位置
思路:
1.确定dp数组以及下标含义
dp[i][j]代表在第i个数字在j状态下的最大长度为dp[i][j]
2.确定递推公式
dp[i]表示以nums[i]作为子序列尾部的最大子序列长度为dp[i]
3.初始化dp数组
dp[0]=1
4.确定遍历顺序
外循环从前往后
内循环从前往后遍历到i-1
5.举例推导
nums=[10,9,2,5,3,7,101,0,1,29,1,20,22,12,102,9,18]
dp
(10, 1)
(9, 1)
(2, 1)
(5, 2)
(3, 2)
(7, 3)
(101, 4)
(0, 1)
(1, 2)
(29, 4)
(1, 2)
(20, 4)
(22, 5)
(12, 4)
(102, 6)
(9, 4)
(18, 5)
6
代码
class Solution(object):
def lengthOfLIS(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
if len(nums) == 1:
return 1
dp = [0 for _ in range(len(nums))]
# 初始化
dp[0] = 1
# 遍历
for i in range(1, len(nums)):
for j in range(i):
# 找到当前数字在之前子序列中的合适位置,比较当前最大长度
if nums[j] < nums[i]:
dp[i] = max(dp[i],dp[j]+1)
elif nums[j] == nums[i]:
dp[i] = max(dp[i],dp[j])
else:
continue
# 如果没有找到合适位置,则表示以该数字作为当前子序列头部,给最大长度赋值为1
if dp[i]==0:
dp[i] = 1
return max(dp)
运行结果
代码精简版
class Solution(object):
def lengthOfLIS(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
if len(nums) == 1:
return 1
dp = [0 for _ in range(len(nums))]
dp[0] = 1
for i in range(1, len(nums)):
for j in range(i):
if nums[j] < nums[i]:
dp[i] = max(dp[i],dp[j]+1)
if dp[i]==0:
dp[i]=1
return max(dp)
运行结果
总结
这道题的难点在于如何判别子序列的长度,必须得从原来所有成型的子序列中依次遍历,不能说只看当前的数字是否加入,因为后面是未知的,你也不知道这个之后的具体变化。