算法导论10.1 Exercises 答案
10.1-1
可以发现,大矩阵\(m\times n\)的所属块号由行坐标和列坐标的最高比特决定。由于是行坐标优先,因此转化成一维序列是,最高的两位坐标为\(i_{\lg m-1},j_{\lg n-1}\)。块内依旧行优先,因此剩下的\(m-1\)比特行坐标排高位,剩下的\(n-1\)比特行坐标排低位。因此最终答案为
\[\langle i_{\lg m-1},j_{\lg n-1},i_{\lg m-2},i_{\lg m-3},\dots,i_1,i_0,j_{\lg n-2},j_{\lg n-3},\dots,j_1,j_0\rangle\]
10.1-2
\(\begin{array}{|l|} \hline \text{PUSH}(S, 4)\\ \hline \text{PUSH}(S, 1)\\ \hline \text{PUSH}(S, 3)\\ \hline \text{POP}(S)\\ \hline \text{PUSH}(S, 8)\\ \hline \text{POP}(S)\\ \hline \end{array} \quad \begin{array}{|l|l|l|l|l|l|} \hline 4\\ \hline 4&1\\ \hline 4&1&3&\phantom{3}&\phantom{3}&\phantom{3}\\ \hline 4&1\\ \hline 4&1&8\\ \hline 4&1\\ \hline \end{array}\)
10.1-3
数组的左边可以用于栈存储,右边也可以用于栈存储。一开始,左栈顶指针栈空时指向左外侧\(0\),如果需要入栈那么将左栈顶指针右移,出栈时将左栈顶指针左移;同样的,右栈顶指针栈空时指向右外侧\(n+1\),如果需要入栈那么将右栈顶指针左移,出栈时将右栈顶指针右移。当这两个栈顶指针恰好相邻时,两个栈都满了(数组\(A\)都占用完成)。可以发现,无论出栈入栈本质上是指针移动一个单位的操作,因此运行时间均为\(O(1)\)。
10.1-4
\(\begin{array}{|l|} \hline \text{ENQUEUE}(Q, 4)\\ \hline \text{ENQUEUE}(Q, 1)\\ \hline \text{ENQUEUE}(Q, 3)\\ \hline \text{DEQUEUE}(Q)\\ \hline \text{ENQUEUE}(Q, 8)\\ \hline \text{DEQUEUE}(Q)\\ \hline \end{array} \quad \begin{array}{|l|l|l|l|l|l|} \hline 4\\ \hline 4&1\\ \hline 4&1&3&\phantom{3}&\phantom{3}&\phantom{3}\\ \hline &1&3\\ \hline &1&3&8\\ \hline & &3&8\\ \hline \end{array}\)
10.1-5
1 | QUEUE-EMPTY(Q) |
10.1-6
将沿用题目10.1-5的两个子程序QUEUE-EMPTY(Q), QUEUE-FULL(Q)
判断双端队列是否为空/满。
1 | HEAD-ENQUEUE(Q) |
10.1-7
假设有两个栈S1, S2
,那么支持队列的两个操作如下进行:
ENQUEUE
直接将元素推入栈S2
中。此操作时间复杂度为\(\Theta(1)\)。DEQUEUE
将S1
栈顶的元素弹出并返回即可。如果S1
为空,那么弹出S2
中的所有元素,一边弹出,一边将元素推入到S1
中,再将元素弹出并返回。这种操作绝大多数时间下都是\(O(1)\),如果栈S2
过于庞大,那么时间开销就是S2
的长度。
1 | // Q.S1和Q.S2表示队列Q内部的两个栈。 |
10.1-8
假设有两个队列Q1, Q2
,那么支持栈的两个操作如下进行(一开始令\(p=0\)):
PUSH:
在队列Qp
队尾推入元素。此操作时间复杂度为\(\Theta(1)\)。POP:
将队列Qp
中的所有元素弹出,除了最后一个元素\(x\),其它元素依次推入到队列Q(3-p)
中,然后赋予p=3-p
,并且将\(x\)返回。此操作时间复杂度为队列Sp
的长度,即\(\Theta(n)\)。