最长上升子序列python
时间: 2023-09-24 20:07:21 浏览: 146
最长上升子序列是指在一个给定序列中,找到一个最长的子序列,使得子序列中的元素是严格递增的。下面是一个用Python实现最长上升子序列的例子:
```python
def longest_increasing_subsequence(nums):
if not nums:
return 0
n = len(nums)
dp = [1] * n
for i in range(1, n):
for j in range(i):
if nums[i] > nums[j]:
dp[i] = max(dp[i], dp[j] + 1)
return max(dp)
nums = [10, 9, 2, 5, 3, 7, 101, 18]
result = longest_increasing_subsequence(nums)
print(result)
```
这段代码中,我们使用动态规划的思想,定义一个dp数组,dp[i]表示以第i个元素结尾的最长上升子序列的长度。初始时,每个元素自成一个长度为1的上升子序列。然后,我们遍历数组,对于每个元素nums[i],通过比较nums[i]与之前的元素nums[j]的大小关系,更新dp数组中的值。最后,返回dp数组中的最大值即可。在给定的例子中,最长上升子序列是[2, 3, 7, 101],其长度为4。
相关问题
895. 最长上升子序列 python
### Python实现最长上升子序列
对于最长上升子序列(Longest Increasing Subsequence, LIS),一种有效的方法是利用动态规划来解决问题。具体来说,定义`dp[i]`表示以第i个元素结尾的最长上升子序列的长度。
为了构建这样的数组,遍历给定列表中的每一个元素,并尝试将其添加到之前所有可能形成的递增子序列之后。如果当前考察的元素大于之前的某个元素,则更新对应的`dp[j]`值(其中j<i)。最终整个过程结束后,最大值即为所求的结果[^1]。
下面给出具体的Python代码实现:
```python
def lengthOfLIS(nums):
if not nums:
return 0
dp = [1]*len(nums)
for i in range(len(nums)):
for j in range(i):
if nums[i]>nums[j]:
dp[i]=max(dp[i],dp[j]+1)
return max(dp)
```
上述函数接受一个整型列表作为输入参数,并返回该列表所能构成的最大递增子序列的长度。这里采用双重循环结构来进行状态转移方程式的计算;外层迭代访问每个位置上的数值,内层则负责寻找能够延长现有增长趋势的位置组合[^3]。
最长上升子序列python动态规划
### Python动态规划实现最长上升子序列
通过动态规划方法可以高效解决最长上升子序列(Longest Increasing Subsequence, LIS)问题。以下是基于给定引用的内容以及补充说明来展示如何使用Python实现该算法。
#### 方法描述
定义一个`dp`数组,其中`dp[i]`表示以第`i`个元素结尾的最长上升子序列的长度。对于每一个位置`i`,我们从前向后扫描所有小于`i`的位置`j`,如果满足条件`nums[i] > nums[j]`,则更新`dp[i] = max(dp[i], dp[j] + 1)`。最终的结果即为整个`dp`数组的最大值。
下面是完整的代码实现:
```python
class Solution:
def lengthOfLIS(self, nums: list[int]) -> int:
if not nums:
return 0
dp = [1 for _ in range(len(nums))] # 初始化DP数组,每个元素至少构成长度为1的子序列
for i in range(1, len(nums)):
for j in range(i):
if nums[i] > nums[j]:
dp[i] = max(dp[i], dp[j] + 1) # 更新当前状态下的最大值
return max(dp) # 返回全局最大值作为结果
```
上述代码的时间复杂度为O(n²),适用于中小规模的数据集[^1]。
为了进一步优化时间性能至O(n log n),可以通过二分查找配合辅助数组完成更高效的解决方案。具体逻辑如下:
```python
import bisect
def lis_optimized(nums: list[int]) -> int:
tails = [] # 辅助数组tails用来记录可能成为候选者的最小尾部元素
for num in nums:
idx = bisect.bisect_left(tails, num) # 找到num应该插入的位置
if idx == len(tails): # 如果大于所有已知尾部,则扩展新序列
tails.append(num)
else: # 否则替换已有尾部使其尽可能小以便后续增长更多
tails[idx] = num
return len(tails) # 最终tail数组大小就是所求LIS长度
```
此版本利用了贪心策略加上二分搜索技术大幅降低了运行开销[^2]。
#### 示例测试
假设输入序列为 `[3,4,-1,5,8,2,3,12,7,9,10]` ,调用函数 `lis_optimized([3,4,-1,5,8,2,3,12,7,9,10])` 将得到输出结果为 `6` 。这表明存在一条严格递增路径经过六个节点形成有效解答之一 [-1 → 2 → 3 → 7 → 9 → 10].
---
###
阅读全文
相关推荐














