T1:重新排列 1234 使得每一个数字都不在原来的位置上,一共有__种排法
解析:
错排公式的运用
n个不同物品,重新排列使得物品不在其原来的位置上。
第一步,把第n个元素放在一个位置,比如位置k,一共有n-1种方法;
第二步,放编号为k的元素,这时有两种情况:
- 把它放到位置n,那么,对于剩下的n-1个元素,
由于第k个元素放到了位置n,剩下n-2个元素就有D(n-2)种方法; - 第k个元素不把它放到位置n,这时,对于这n-1个元素,有D(n-1)种方法;
综上得到
D(n) = (n-1) [D(n-2) + D(n-1)]
特殊地,D(1) = 0, D(2) = 1.
T2:一棵结点数为 2015 的二叉树最多有___个叶子结点。
如果根的高度为 1,具有 61 个结点的完全二叉树的高度为( )
…
解析:
二叉树的性质:
- 性质一:
在二叉树的第i层上最多有2 i − 1 ^{i-1} i−1个节点(i>=1) - 性质二
深度为k的二叉树至多有 2 k 2^k 2k-1个节点(k>=1) - 性质三
对于任意一个二叉树,如果其叶子节点个数为n0,有两个儿子的节点数为n2,一个儿子的个数为n1,
则一定满足:
n0=n2+1
总儿子个数为:n1+2n2 - 性质四
具有n个节点的完全二叉树的深度为floor( log 2 n \log^n_2 log2n)+1 - 性质五
对于一棵n个节点的完全二叉树,对任一个节点(编号为i)
T3:已知一个无向完全图G有5个节点,则他共有()条边
解析:
对于无向完全图的定义,图中每对点恰好有一条边。
如果顶点为n的话每个点可与其它n-1个点相连共有n*(n-1),但是每条线均被计算了2次(比如从A到B和从B连到A是一样的),再除以2即可n*(n-1)/2。
T4:T(n)=aT( n b \tfrac{n}{b} bn)+ n d n^d nd
解析:
主定理
- 当 l o g b a < d log_ba<d logba<d,时间复杂度为: O ( n d ) O(n^d) O(nd)
- 当 l o g b a > d log_ba>d logba>d,时间复杂度为: O ( n l o g b a ) O(n^{log_ba}) O(nlogba)
- 当 l o g b a = d log_ba=d logba=d,时间复杂度为: O ( n d log n ) O(n^d\log n) O(ndlogn)
T5:以下编程语言中,同时符合面向对象与编译执行的是( )
解析:
面向对象的语言:jave,c++,c#,python,golang
-
编译:将源代码一次性转换成目标代码的过程
类似英语中的全文翻译。
执行编译过程的程序叫做编译器。 -
解释:将源代码逐条转换成目标代码同时逐条运行的过程。
类似英语中的同声传译。
执行解释过程的程序叫做解释器。
T6:在一个长度为n的数组中找到第k大的数字,平均的算法时间复杂度最低的是:
解析:
给定一个数组A,要求找到数组A中第K大的数字。对于这个问题,解决方案有不少,此处我只给出三种:
方法1:
对数组A进行排序,然后遍历一遍就可以找到第K大的数字。该方法的时间复杂度为O(N*logN)
方法2:
利用简单选择排序法的思想,每次通过比较选出最大的数字来,比较上K次就能找出第K大的数字来。该方法的时间复杂度为O(N*K),最坏情况下为O(N^2)。
方法3:
这种方法是本文谈论的重点,可以利用快排的思想,首先快排每次执行都能确定一个元素的最终的位置,如果这个位置是n-k(其中n是数组A的长度)的话,那么就相当于找到了第K大的元素。设确定的元素位置m的话,如果m > n - k大的话,那么第K大的数字一定
注意:
- 第K大的数字在数组中对应的位置为n-k(按照升序排序的话)。
- 该算法的时间复杂度整体上为O(N)。
- 需要注意的是:这种方法会改变数组中元素的顺序,即会改变数组本身。
- 如果要求第K小的数字的话,只需把n-k换成k-1即可(升序排序)。
接下来,我们仔细分析一下方法3的时间复杂度,其实方法3在《算法导论》第九章有着比较详细的描述,但《算法导论》说的是期望为线性时间的选择算法,即该算法的时间复杂度在平均情况下或者一般情况下为O(n);因为此处利用的快排的思想,而快排的时间
复杂度在一般情况下为O(N*logN),但在最坏的情况下(即整个数组原本就是有序的情况)时间复杂度为O(N2)。所以说对于方法3,《算导》最后给定结果是这样的:平均时间复杂度为O(N),最坏情况下的时间复杂度为O(N2)。
但是,此处的“平均”同快排一样,是适用于绝大数的情况的。所以我们通常说该算法的时间复杂度为O(N)。
- 我们要搞清楚一点,快排是对参考元素两边都进行递归,而我们的方法3只考虑参考元素的一边,即只对一边进行递归。
- 我们可以粗略的估计下(具体计算还是参考《算导》),在一般情况下方法3的时间复杂度计算公式,假设我们的数据足够的随机,每次划分都在数据序列的中间位置,根据条件1,那么第一次划分我们需要遍历约n个数,第二次需要遍历约n/2个数,…,这样递归下去,最后:
当m趋于无穷大时,该式子收敛于2n,故可以认为其期望时间复杂度为O(N).