c语言最长递增子序列nlogn,十月常见算法考题、最长递增子序列,Leetcode第300题最长上升子...

十月常见算法考题、最长递增子序列,Leetcode第300题最长上升子

十月常见算法考题、最长递增子序列,Leetcode第300题最长上升子序列的变种,我没见过乔丹,今天詹姆斯就是我的神!

@Author:Runsen

@Date:2020/10/12

d4cccf3136f6787205fd59470ea72cc9.png

十月过得很平缓。在这个“收获的季节”,我成了为数不多不必收获的人。每天睡到中午,即使闹钟设在早上也很难把自己弄醒。

十月没有重要的待办事项、非做不可的作业,也没有实习,人好像被社会排除在外,只有日期的变化和昼夜的流动,变成这个月很重要的刻度,甚至盼头:朝盼暮,暮盼朝,明日永复,往昔不溯洄。

十五号又要补考化工原理,本不想写博客了,好好看看化工原理,刷题,谁想不到今天詹姆斯FMVP,我本不是湖人的粉,而是詹姆斯的粉丝,于是又花点时间写下博客了。

牛客:最长递增子序列常考算法问题

如果我只写日记,不写代码IT之类的都不好意思发CSDN博客了,那顺便把前几天我搞不懂了最长递增子序列算法写一下吧。

41e50c248d9c9e708c6558a45717046f.png

牛客题目:https://www.nowcoder.com/practice/9cf027bf54714ad889d4f30ff0ae5481

题目是这样的,有一个整数序列,例如 1, 6, 8, 2, 4, 5, 9,在这个数列中找到一个长度最长的递增子数列。(不是长度)

输入

[2,1,5,3,6,4,8,9,7]

输出

[1,3,4,8,9]

输入

[1,2,8,6,4]

输出

[1,2,4]

说明

其最长递增子序列有3个,(1,2,8)、(1,2,6)、(1,2,4)其中第三个字典序最小,故答案为(1,2,4)

此题,之前还有类似的,类似的牛客题目

Leetcode300 最长上升子序列

其实这道题,我马上就想到了Leetcode300 最长上升子序列的两次动态规划做法。

def getMaxSubList(nums):

# 如果定义dp dp[i] 最长上升子序列 那么 dp[i] = max(dp[i], dp[k] + 1) 0

m = len(nums)

if m <= 1:

return m

dp = [ 1 for _ in range(m)]

for i in range(1,m):

for j in range(i):

if nums[i] > nums[j]:

dp[i] = max(dp[i], dp[j]+ 1 )

print(dp)

return max(dp)

print(getMaxSubList([1,3,6,7,9,4,10,5,6]))

[1, 2, 3, 4, 5, 3, 6, 4, 5]

6

在这里的dp指的是第i个最长上升子序列的长度,而牛客的是要求出对应的上升子序列。于是乎就转成了,通过dp和arr两个数组来求出 最长上升子序列。

首先遍历找到dp数组中的最大值maxlen以及下标index,其中maxlen就是最长递增子序列的长度,arr[index]就是最长递增子序列的最后一个数字,然后从index向前遍历数组arr,找到比arr[index]小的数arr[j]并且dp[j] + 1 = dp[index]。这个值就是子序列的倒数第二个数,依次向前遍历即可得到最长递增子序列。

'''

@Author: Runsen

@WeChat:RunsenLiu

@微信公众号: Python之王

@CSDN: https://blog.csdn.net/weixin_44510615

@Github: https://github.com/MaoliRUNsen

@Date: 2020/10/12

'''

def getMaxSubList(nums):

# 如果定义dp dp[i] 最长上升子序列 那么 dp[i] = max(dp[i], dp[k] + 1) 0

m = len(nums)

if m <= 1:

return m

dp = [ 1 for _ in range(m)]

for i in range(1,m):

for j in range(i):

if nums[i] > nums[j]:

dp[i] = max(dp[i], dp[j]+ 1 )

print(dp)

return dp

def generateLIS(arr, dp):

# 因为要找到最小的字典序,max的方法是找到第一个,而不是最后一个

maxlen = max(dp)

index = dp.index(max(dp))

# maxlen = index = 0

# for i in range(len(dp)):

# if dp[i] >= maxlen:

# maxlen = dp[i]

# index = i

# maxlen是dp中最大值,index只是对应的index

# lis

lis = [None for _ in range(maxlen)]

# lis最后一个一定是最大值

lis[maxlen-1] = arr[index]

# maxlen需要减一

maxlen = maxlen - 1

# 倒序

for i in range(index, -1, -1):

# 寻找倒数的数

if arr[i] < arr[index] and dp[i]+1 == dp[index]:

lis[maxlen-1] = arr[i]

maxlen = maxlen - 1

index = i

return lis

print(generateLIS([1,3,6,7,9,4,10,5,6],getMaxSubList([1,3,6,7,9,4,10,5,6])))

print(generateLIS([1,2,8,4],getMaxSubList([1,2,8,4])))

[1, 2, 3, 4, 5, 3, 6, 4, 5]

[1, 3, 6, 7, 9, 10]

[1, 2, 3, 3]

[1, 2, 8]

但是由于最后的结果是最小的字典序,max的方法是找到第一个,而不是最后一个,需要修改max的写法。

# 最长递增子序列

def getMaxSubList(arr):

def getdp(arr):

m = len(arr)

if m <= 1:

return m

dp = [1 for _ in range(m)]

for i in range(1, m):

for j in range(i):

if arr[i] > arr[j]:

dp[i] = max(dp[i], dp[j] + 1)

print(dp)

return dp

def generateLIS(arr, dp):

maxlen = index = 0

for i in range(len(dp)):

if dp[i] >= maxlen: # >= 如果是max就是>

maxlen = dp[i]

index = i

lis = [None for _ in range(maxlen)]

# lis最后一个一定是最大值

lis[maxlen - 1] = arr[index]

# maxlen需要减一

maxlen = maxlen - 1

# 倒序

for i in range(index, -1, -1):

# 寻找倒数的数

if arr[i] < arr[index] and dp[i] + 1 == dp[index]:

lis[maxlen - 1] = arr[i]

maxlen = maxlen - 1

index = i

return lis

if arr == None or len(arr) == 0:

return None

dp = getdp(arr)

return generateLIS(arr, dp)

print(getMaxSubList([2, 1, 5, 3, 6, 4, 8, 9, 7]))

print(getMaxSubList([1, 2, 8, 4]))

[1, 2, 3, 4, 5, 3, 6, 4, 5]

[1, 3, 6, 7, 9, 10]

[1, 2, 3, 3]

[1, 2, 4]

上面的代码运行超时。

53a425833bfa3d2afee82eb6f9a84291.png

贪心+二分的巧妙解决Leetcode300

Leetcode300题最长上升子序列可以用 贪心+二分,具体的代码查看Leetcode。

如果插入的i比如前面的最后一个小,就寻找第一个大于等于的值,替换,典型的二分查找变种。

arr = [2, 1, 5, 3, 6, 4, 8, 9, 7]

d = []

for n in arr:

if not d or n > d[-1]:

d.append(n)

else:

l, r = 0, len(d) - 1

loc = r

while l <= r:

mid = (l + r) // 2

if d[mid] >= n:

loc = mid

r = mid - 1

else:

l = mid + 1

d[loc] = n

print(d)

print(len(d))

[1, 3, 4, 7, 9]

5

一开始我以为就是这样,但是如果arr是[100,101,102,103,1,2,3],得到的d不是[100,101,102,103]。

arr = [100,101,102,103,1,2,3]

d = []

for n in arr:

if not d or n > d[-1]:

d.append(n)

else:

l, r = 0, len(d) - 1

loc = r

while l <= r:

mid = (l + r) // 2

if d[mid] >= n:

loc = mid

r = mid - 1

else:

l = mid + 1

d[loc] = n

print(d)

print(len(d))

[1, 2, 3, 103]

4

可以说这种的二分其实并不能求出最长递增子序列,因此唯一的方法就是求出dp,然后根据dp和arr求出最长递增子序列。

柳暗花明又一村

在我怀疑人生的时候,竟然看到了一个通过辅助数组ends来缩短时间复杂度到O(nlogn)。本质上还是二分。

f84291d3a8a6892bdc7d6ead6d667fab.png

具体博客参考:https://blog.csdn.net/qq_34342154/article/details/77132137

下面是最终通过的代码。

class Solution:

def LIS(self, arr):

def getdp(arr):

# 求dp

dp = [0 for _ in range(len(arr))]

ends = [0 for _ in range(len(arr))]

right = 0

dp[0] = 1

ends[0] = arr[0]

# 二分法进行

for i in range(1, len(arr)):

l = 0

r = right

while l <= r:

m = (l + r) // 2

if arr[i] > ends[m]:

l = m + 1

else:

r = m - 1

right = max(right, l)

dp[i] = l + 1

ends[l] = arr[i]

return dp

def generateLIS(arr, dp):

maxlen = index = 0

for i in range(len(dp)):

if dp[i] >= maxlen: # >= 如果是max就是>

maxlen = dp[i]

index = i

lis = [None for _ in range(maxlen)]

# lis最后一个一定是最大值

lis[maxlen - 1] = arr[index]

# maxlen需要减一

maxlen = maxlen - 1

# 倒序

for i in range(index, -1, -1):

# 寻找倒数的数

if arr[i] < arr[index] and dp[i] + 1 == dp[index]:

lis[maxlen - 1] = arr[i]

maxlen = maxlen - 1

index = i

return lis

if arr == None or len(arr) == 0:

return None

dp = getdp(arr)

return generateLIS(arr, dp)

后来看了别人的题解,我看废了。

84489bb4cae79e2a1477a47a56de2450.png

后言(日记)

今天湖人总冠军,詹姆斯FMVP!

如果这个世界上真有超级英雄,他的名字一定叫勒布朗-詹姆斯。

732162f79aaa4255a791dbc3a36ad5ec.png

已是十七生涯,犹能横刀立马。

三队四冠不足夸,再看风吹浪打。

终结十年无冠,奖杯聊显光华。

鏖战竞透紫金甲,今夜致敬曼巴。

每个年代都有各自的英雄!

78cecee495ec46bc23ae66e1187e90d2.png

我没见过乔丹,詹姆斯就是我的神!

十月常见算法考题、最长递增子序列,Leetcode第300题最长上升子相关教程

FedML联邦机器学习框架正式开源助力算法开发和性能比较

FedML联邦机器学习框架正式开源,助力算法开发和性能比较 Federated Learning 联邦学习是机器学习领域中快速发展的研究领域。尽管已经进行了大量的研究工作,但是现有的软件框架不能充分支持多样化的算法开发(例如,多样化的拓扑和灵活的消息交换),并且实

【啃书】《智能优化算法及其MATLAB实例》例5.1蚁群算法求解TSP问

【啃书】《智能优化算法及其MATLAB实例》例5.1蚁群算法求解TSP问题 文章目录 问题描述 仿真过程 matlab源码 问题描述 仿真过程 matlab源码 %20201012lu注:该matlab代码成功在matlabR2019a运行%%%%%%%%%%%%%%%%%%%%蚁群算法解决TSP问题%%%%%%%%%%%%%%%%%%%%%%

决策树--鸢尾花

决策树--鸢尾花 决策树CART算法后剪枝损失函数理解: 从下至上剪枝: 当以最下边的某个节点分别作为根节点和叶子节点时,剪掉前后,此单个节点(作为叶子和根节点)函数损失值相同,从整体函数而言,减小了一个叶子,在此情况下,alpha = g(t),因此减小了一个

动态规划算法-LCS

动态规划算法-LCS 为什么80%的码农都做不了架构师? 本讲我们来探讨动态规划算法中一个常见的问题最长公共子序列即LCS(Long Common Sequence)。 首先我们来看一下问题描述: 有两个序列X和Y,其中 X = {x1, x2, ..., xm} Y = {y1, y2, ..., yn} 求X和Y的最长

knn最近邻算法_k最近邻knn算法

knn最近邻算法_k最近邻knn算法 knn最近邻算法 Data science is hot and it seems that everybody is working on some sort of project involving the latest state-of-the-art (SOTA) algorithm. Of course with good reason as in many cases we can use dat

Java迪杰斯特拉算法求单源点最短路径

Java迪杰斯特拉算法求单源点最短路径 求A到其它点的最短路径 输入 6 9 0 3 28 0 2 4 1 0 2 1 4 10 2 1 15 2 5 8 4 3 4 5 4 18 5 3 13 import java.util.Scanner;public class Main26 {static int INF = Integer.MAX_VALUE;// 无法到达public static void main

Mahout算法集

Mahout算法集 为什么80%的码农都做不了架构师? Apache Mahout 是 ApacheSoftware Foundation (ASF) 旗下的一个开源项目,提供一些可扩展的机器学习领域经典算法的实现,旨在帮助开发人员更加方便快捷地创建智能应用程序,并且,在 Mahout 的最近版本中还加

Flv.js全面解析

Flv.js全面解析 Flv.js全面解析 常见直播协议 Flv.js概览 Flv.js结构图 架构图 功能 API文档相关 MediaDataSource的字段列表如下, Config flvjs.getFeatureList() Flv.js兼容性 直播服务器搭建 推流 ffmpeg推流 OBS推流 flv.js搭建过程 下载链接 flv.js Demo

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值