基于CBA的算法对所有大小为n的多个数组比较大小的算法的时间复杂度为(nlog(n))

虽是读书笔记但是如转载请注奣出处

1. LCS(最长公共子序列)O(n^2)的时间复杂度,O(n^2)的空间复杂度;
2. 与之类似但不同的最长公共子串方法。
最长公共子串用动态规划可实现O(n^2)的时间复雜度O(n^2)的空间复杂度;还可以进一步优化,用后缀多个数组比较大小的算法的方法优化成线性时间O(nlogn);空间也可以用其他方法优化成线性
3.LIS(最长递增序列)DP方法可实现O(n^2)的时间复杂度,进一步优化最佳可达到O(nlogn)


字符串 X Y 长度 分别mn

一个数列 S如果分别是两个或多个已知数列的子序列,且是所有符合此条件序列中最长的则 S 称为已知序列的最长公共子序列。
例如:输入两个字符串 BDCABA 和 ABCBDAB字符串 BCBA 和 BDAB 都是是它们的最长公囲子序列,则输出它们的长度 4并打印任意一个子序列. (Note: 不要求连续)

判断字符串相似度的方法之一 - LCS 最长公共子序列越长,越相似

对于┅般性的 LCS 问题(即任意数量的序列)是属于 NP-hard。但当序列的数量确定时问题可以使用动态规划(Dynamic Programming)在多项式时间解决。可达时间复杂度:O(m*n)


遞归结构容易看到最长公共子序列问题具有子问题重叠性质例如,在计算 XY 的最长公共子序列时可能要计算出 XYn-1Xm-1Y 的最长公共子序列。而这两个子问题都包含一个公共子问题即计算 Xm-1Yn-1 的最长公共子序列。

递归结构容易看到最长公共子序列问题具有子问题重叠性质唎如,在计算 XY 的最长公共子序列时可能要计算出 XYn-1Xm-1Y 的最长公共子序列。而这两个子问题都包含一个公共子问题即计算Xm-1Yn-1 的最长公共子序列。

子问题空间中总共只有O(m*n) 个不同的子问题,因此用动态规划算法自底向上地计算最优值能提高算法的效率。

长度表C 和 方向變量B:

* 需要计算 m*n 个子问题的长度 即 任意c[i][j]的长度 // 动态规划计算所有子问题

这个 LCS 跟前面说的最长公共子序列的 LCS 不一样不过也算是 LCS 的一个变体,在 LCS 中子序列是不必要求连续的,而子串则是 “连续” 的

我们还是像之前一样 “从后向前” 考虑是否能分解这个问题类似最长公共子序列的分析,这里我们使用c[i,j] 表示 以 XiYj 结尾的最长公共子串的长度,因为要求子串连续所以对于 XiYj 来讲,它们要么与之前的公共子串构荿新的公共子串;要么就是不构成公共子串故状态转移方程

* 需要计算 m*n 个子问题的长度 即 任意c[i][j]的长度

时间复杂度O(nlogn)的后缀多个数组比较大小嘚算法的方法


前面提过后缀多个数组比较大小的算法的基本定义,与子串有关可以尝试这方面思路。由于后缀多个数组比较大小的算法朂典型的是寻找一个字符串的重复子串所以,对于两个字符串我们可以将其连接到一起,如果某一个子串 s 是它们的公共子串则 s 一定會在连接后字符串后缀多个数组比较大小的算法中出现两次,这样就将最长公共子串转成最长重复子串的问题了这里的后缀多个数组比較大小的算法我们使用基本的实现方式。

值得一提的是在找到两个重复子串时,不一定就是 X 与 Y 的公共子串也可能是 X 或 Y 的自身重复子串,故在连接时候我们在 X 后面插入一个特殊字符‘#’即连接后为 X#Y。这样一来只有找到的两个重复子串恰好有一个在 #的前面,这两个重复孓串才是 X 与 Y 的公共子串

设字符串 X 的长度为 mY 的长度为 n,最长公共子串长度为 l
对于基本算法(brute force),X 的子串(m 个)和 Y 的子串(n 个)一一对比最坏情况下,复杂度为 O(m*n*l)空间复杂度为 O(1)。
对于 DP 算法由于自底向上构建最优子问题的解,时间复杂度为 O(m*n);空间复杂度为 O(m*n)当然这里是可鉯使用滚动多个数组比较大小的算法来优化空间的,滚动多个数组比较大小的算法在动态规划基础回顾中多次提到
对于后缀多个数组比較大小的算法方法,连接到一起并初始化后缀多个数组比较大小的算法的时间复杂度为 O(m+n)对后缀多个数组比较大小的算法的字符串排序,甴于后缀多个数组比较大小的算法有 m+n 个后缀子串子串间比较,故复杂度为 O((m+n)*l*lg(m+n))求得最长子串遍历后缀多个数组比较大小的算法,复杂度为 O(m+n)所以总的时间复杂度为 O((m+n)*l*lg(m+n)),空间复杂度为 O(m+n)
总的来说使用后缀多个数组比较大小的算法对数据做一些 “预处理”,在效率上还是能提升不尐的

1.2 重叠的子问题:
所以填表时候就是建立一个多个数组比较大小的算法DP[i], 记录以arr[i]为序列末尾的LIS长度。

首先通过一个多个数组比较大小的算法MaxV[nMaxLength]来缓存递增子序列LIS的末尾元素最小值;通过nMaxLength 记录到当前遍历为止的最长子序列的长度;

  • if > 说明j能够放在最长子序列的末尾形成一个新的最長子序列.
  • if< 说明j需要替换前面一个刚刚大array[j]的元素

最后输出LIS时候,我们会用一个LIS[]多个数组比较大小的算法这边LIS[i]记录的是以元素arr[i]为结尾的朂长序列的长度



// 新元素 更小,更有“潜力”替换大的元素 // 在MaxV多个数组比较大小的算法中查找一个元素刚刚大于arr[i]

* : MaxV里面的多个数组比较大小嘚算法下标代表了长度为index的最长子序列末尾元素,反过来就是末尾元素在MaxV里对应的下标就是他子序列的长度


  • 给一个字符串求这个字符串朂少增加几个字符能变成回文
  • 要在一条河的南北两边的各个城市之间造若干座桥.桥两边的城市分别是 a(1)...a(n) 和 b(1)...b(n). 且南边 a(1)...a(n) 是乱序的,北边同理但昰要求 a(i) 只可以和 b(i) 之间造桥, 同时两座桥之间不能交叉. 希望可以得到一个尽量多座桥的方案.

以我和蓝盆友的讨论做结:

- 通常DP是一个不算最好,泹是比最直接的算法好很多的方法 DP一般是O(n^2);但是如果想进一步优化 O(nlogn)就要考虑其他的了

- 对,要想更好的方法就是要挖掘题目本身更加隐匿的性质了


想更一进步的支持我请扫描下方的二维码,你懂的~

}

1.在一个二维多个数组比较大小的算法中每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序请完成一个函数,输入这样的一个二维多个数組比较大小的算法和一个整数判断多个数组比较大小的算法中是否含有该整数。

  • 矩阵是有序的从左下角来看,向上数字递减向右数芓递增,
  • 因此从左下角开始查找当要查找数字比左下角数字大时。右移
  • 要查找数字比左下角数字小时上移

2.请实现一个函数,将一个字苻串中的空格替换成“%20”例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy

3.输入一个链表,从尾到头打印链表每个节点的值
思路:使用┅个栈来存储链表值。

4.输入某二叉树的前序遍历和中序遍历的结果请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含偅复的数字例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回

5 用两个栈来实现一个队列,完成队列的Push和Pop操作 队列中的元素为int类型。

6.把一个多个数组比较大小的算法最开始的若干个元素搬到多个数组比较大小的算法的末尾我们称之为多个数组比较大小的算法的旋转。 输入一个非递减排序的多个数组比较大小的算法的一个旋转输出旋转多个数组比较大小的算法的最小元素。例如多个数组比較大小的算法{3,4,5,1,2}为{1,2,3,4,5}的一个旋转该多个数组比较大小的算法的最小值为1。 NOTE:给出的所有元素都大于0若多个数组比较大小的算法大小为0,请返回0

7.现在要求输入一个整数n请你输出斐波那契数列的第n项。

8.一只青蛙一次可以跳上1级台阶也可以跳上2级。求该青蛙跳上一个n级的台阶總共有多少种跳法

9.一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级求该青蛙跳上一个n级的台阶总共有多少种跳法。

10.輸入一个整数输出该数二进制表示中1的个数。其中负数用补码表示

11.输入一个链表,输出该链表中倒数第k个结点

思路:两个指针,先讓第一个指针和第二个指针都指向头结点然后再让第一个指正走(k-1)步,到达第k个节点然后两个指针同时往后移动,当第一个结点到达末尾的时候第二个结点所在位置就是倒数第k个节点了。

12.输入一个整数多个数组比较大小的算法实现一个函数来调整该多个数组比较大小嘚算法中数字的顺序,使得所有的奇数位于多个数组比较大小的算法的前半部分所有的偶数位于位于多个数组比较大小的算法的后半部汾,并保证奇数和奇数偶数和偶数之间的相对位置不变。

13.输入一个链表反转链表后,输出链表的所有元素

/r1,r2分别为自己写的递归与非遞归方法

14.输入两个整数序列,第一个序列表示栈的压入顺序请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等例如序列1,2,3,4,5是某栈的压入顺序,序列45,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列(注意:这两个序列的長度是相等的)

【思路】借用一个辅助的栈,遍历压栈顺序先讲第一个放入栈中,这里是1然后判断栈顶元素是不是出栈顺序的第一个え素,这里是4很显然1≠4,所以我们继续压栈直到相等以后开始出栈,出栈一个元素则将出栈顺序向后移动一位,直到不相等这样循环等压栈顺序遍历完成,如果辅助栈还不为空说明弹出序列不是该栈的弹出顺序。

首先1入辅助栈此时栈顶1≠4,继续入栈2
此时栈顶2≠4继续入栈3
此时栈顶3≠4,继续入栈4
此时栈顶4=4出栈4,弹出序列向后一位此时为5,,辅助栈里面是1,2,3
此时栈顶3≠5继续入栈5
此时栈顶5=5,出栈5,彈出序列向后一位此时为3,,辅助栈里面是1,2,3
依次执行最后辅助栈为空。如果不为空说明弹出序列不是该栈的弹出顺序

15.输入一个整数多個数组比较大小的算法,判断该多个数组比较大小的算法是不是某二叉搜索树的后序遍历的结果如果是则输出Yes,否则输出No。假设输入的多個数组比较大小的算法的任意两个数字都互不相同

思路:BST的后序序列的合法序列是,对于一个序列S最后一个元素是x (也就是根),如果去掉最后一个元素的序列为T那么T满足:T可以分成两段,前一段(左子树)小于x后一段(右子树)大于x,且这两段(子树)都是合法嘚后序序列完美的递归定义。

16.输入一颗二叉树和一个整数打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结點开始往下一直到叶结点所经过的结点形成一条路径


  

17.输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打茚出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba

18.多个数组比较大小的算法中有一个数字出现的次数超过多个数组比较大小的算法长度的一半,請找出这个数字例如输入一个长度为9的多个数组比较大小的算法{1,2,3,2,2,2,5,4,2}。由于数字2在多个数组比较大小的算法中出现了5次超过多个数组比较夶小的算法长度的一半,因此输出2如果不存在则输出0。

思路:多个数组比较大小的算法排序后如果符合条件的数存在,则一定是多个數组比较大小的算法中间那个数

20.输入n个整数,找出其中最小的K个数

思路:基于堆排序算法构建最大堆。时间复杂度为O(nlogk);
如果用快速排序时间复杂度为O(nlogn);
1.将前k个元素构造成最大堆(0~k-1)
2.从k位开始,依次与最大堆的堆顶元素进行比较如果比堆顶小,则该数与堆顶交换位置维护最大堆
3.最后从k-1~0的数是最小的k的数

21.求出任意非负整数区间中1出现的次数。如:算出100~1300的整数中1出现的次数

22.把只包含因子2、3和5的数称作醜数(Ugly Number)。例如6、8都是丑数但14不是,因为它包含因子7 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数

23.在一个字符串(1<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置

24.给定一个二叉树和其中的一个结点请找出中序遍历顺序嘚下一个结点并且返回。注意树中的结点不仅包含左右子结点,同时包含指向父结点的指针

分析二叉树的下一个节点,一共有以下情況:
1.二叉树为空则返回空;
2.节点右孩子存在,则设置一个指针从该节点的右孩子出发一直沿着指向左子结点的指针找到的叶子节点即為下一个节点;
3.节点不是根节点。如果该节点是其父节点的左孩子则返回父节点;否则继续向上遍历其父节点的父节点,重复之前的判斷返回结果。

25.给定一颗二叉搜索树请找出其中的第k大的结点。例如 5 / \ 3 7 /\ /\ 2 4 6 8 中,按结点数值大小顺序第三个结点的值为4

思路:二叉搜索树按照中序遍历的顺序打印出来正好就是排序好的顺序。所以按照中序遍历顺序找到第k个结点就是结果。


常用算法2:二叉树的创建及遍历


瑺用算法4:快速排序:

}

我要回帖

更多关于 多个数组比较大小的算法 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信