算法题笔记

来源:互联网 发布:免费游戏挂机软件 编辑:程序博客网 时间:2024/05/22 13:05

即将面临找工作的问题,记录下复习算法工程中遇到的比较好的题目和解法,欢迎大家讨论。


1、请给出一个O(nlogn)的算法,使之能够找出一个n个数的序列中最长的单调递增子序列。

这是算法导论中的一道课后题。

解法一:利用求最长公共子序列的思想,将n个数的序列A先排序形成一个有序的序列B,然后利用动态规划的思想求A与B的最长公共子序列,得到的最长公共子序列就是所求的解。但是我们知道最长公共子序列的解法是O(n2),所以不满足题目要求,此法不通。

解法二:对包含n个数的序列A,我们使用一个数组C,其中C[i]记录长度为i的所有单调递增子序列的最小的元素(可能说的不清楚,举例说明比如A有3个长为2的单调递增子序列1,2;3,4;5,6;那么C[2]的值就是2,记录的是最小的那个子序列的最后一个元素)。具体的遍历过程是对于一个元素A[i],通过二分查找C(因为C是有序数组),获取A[i]的位置flag,比较A[i]与C[flag]的大小,如果小于C[falg]用A[i]替换C[flag],如果大于用A[i]替换C[flag+1]。这样遍历一遍就能得到数组A的最长的公共子序列的长度,但是要获得最长公共子序列的组成,需要利用第一次遍历获得长度,再遍历一次,在给定的长度时将C中的元素拷贝出来,防止后边可能进行的破坏。虽然需要遍历两边但是满足时间复杂度的要求,大家有更好的方法欢迎讨论。


2、请给出一个时间为O(nlgk)、用来将k个已排序链表合并为一个排序链表的算法。

lgk我们可以想到要么通过折半查找,要么将将k个数构造成一个树形的结构。

将k个排序的链表的指向第一个元素的指针组成一个最小堆,每次取最小的一个元素,获取最小的元素后将第二元素顶替原来的元素,执行一次Max_heapify(),直到某个链表为空,若为空将空链表与最后一个链表交换同样执行一次Max_heapify()。