跳到主要内容

名古屋大学 情報学研究科 複雑系科学専攻 2018年8月実施 情3

Author

祭音Myyura

Description

相異なる nn 個の自然数を、インデックス 11 から nn の一次元配列 AA に格納する。
1kn1\le k\le n に対し、列中の kk 番目に小さい値を返す関数 k_th を、次の関数 partition を用いて作る。

partition(A,i,j) は、i=ji=j なら ii を返す。i<ji<j なら pivot = A[j] とし、区間 A[i],,A[j]A[i],\ldots,A[j] を並べ替えて、pivot が格納されたインデックス pp を返す。返却時には

A[i],,A[p]pivot,A[p],,A[j]pivotA[i],\ldots,A[p]\le \mathrm{pivot}, \qquad A[p],\ldots,A[j]\ge \mathrm{pivot}

が成り立つ。

手続き `partition(A,i,j)`
1. もし i と j が等しければ、i を返し、手続きを終了する。
2. 変数 pivot に A[j] の値を代入する。
3. 変数 id に i の値を代入する。
4. 変数 ip に i の値を代入する。
5. 繰り返し begin
6. もし id の値と j の値が等しければ、繰り返しを終了する。
7. もし A[id] の値が pivot の値以下であれば、
8. begin
9. A[ip] の値と A[id] の値を交換する。
11. ip + 1 の値を ip に代入する。
12. end
13. id + 1 の値を id に代入する。
14. 繰り返し end
15. A[ip] の値と A[j] の値を交換する。
16. ip の値を返し、手続きを終了する。

[1] n=8n=8 の配列

インデックス12345678
BB5010803070204060

に対して partition(B,3,7) を実行する。idip または配列 BB に対する操作が行われる行番号と、その操作後の状態をすべて示し、返り値も答えよ。見かけ上、配列が変化しない交換も省略しないものとする。

[2] 配列 AA が次を満たすとする。

  • インデックスが ii より小さい全要素は、インデックスが ii 以上の全要素より小さい。
  • インデックスが jj より大きい全要素は、インデックスが jj 以下の全要素より大きい。

このとき partition(A,i,j)pp を返したなら、配列 AA における pp 番目に小さい自然数を求め、その理由を述べよ。

[3] 問 [2] の条件の下で ikji\le k\le j とする。partition(A,i,j)pp を返したとき、

  1. p>kp>k なら、kk 番目に小さい自然数はどのインデックス範囲にあるか。
  2. p<kp<k なら、kk 番目に小さい自然数はどのインデックス範囲にあるか。

[4] k_th(A,1,n,k)kk 番目に小さい自然数を返すように、次の空欄を埋めよ。

手続き k_th(A,i,j,k)

1. 変数 p に partition(A,i,j) が返す値を代入する。
2. もし(ア)であれば、(イ)を返し、手続きを終了する。
3. もし(ウ)であれば、(エ)を返し、手続きを終了する。
4. もし(オ)であれば、(カ)を返し、手続きを終了する。

Kai

[1]

pivot = B[7] = 40 である。

  • id=380>4080>40 なので交換せず、id を 4 にする。
  • id=4304030\le40 なので B[3]B[3]B[4]B[4] を交換し、ip を 4 にする。
  • id=570>4070>40 なので交換しない。
  • id=6204020\le40 なので B[4]B[4]B[6]B[6] を交換し、ip を 5 にする。
  • id=7=j で反復を終え、B[5]B[5]B[7]B[7] を交換する。
行番号id の値ip の値配列 BB の要素の並び
33未定50 10 80 30 70 20 40 60
43350 10 80 30 70 20 40 60
124350 10 80 30 70 20 40 60
94350 10 30 80 70 20 40 60
104450 10 30 80 70 20 40 60
125450 10 30 80 70 20 40 60
126450 10 30 80 70 20 40 60
96450 10 30 20 70 80 40 60
106550 10 30 20 70 80 40 60
127550 10 30 20 70 80 40 60
147550 10 30 20 40 80 70 60

したがって、

partition(B,3,7)=5\boxed{\operatorname{partition}(B,3,7)=5}

であり、終了時の配列は

(50,10,30,20,40,80,70,60)\boxed{(50,10,30,20,40,80,70,60)}

である。

[2]

partition の終了時には

A[p]=pivotA[p]=\mathrm{pivot}

であり、自然数は相異なるので、

A[q]<A[p](iq<p),A[q]>A[p](p<qj)A[q]<A[p]\quad(i\le q<p),\qquad A[q]>A[p]\quad(p<q\le j)

となる。

さらに仮定より、

A[q]<A[p](q<i),A[q]>A[p](q>j)A[q]<A[p]\quad(q<i),\qquad A[q]>A[p]\quad(q>j)

である。したがって A[p]A[p] より小さい要素はちょうど p1p-1 個である。

よって、pp 番目に小さい自然数は

A[p]\boxed{A[p]}

である。これは partition 呼出し前の pivot、すなわち元の A[j]A[j] の値でもある。

[3]

問 [2] より、A[p]A[p] は配列全体で pp 番目に小さい。

  1. p>kp>k のとき、kk 番目に小さい自然数は

    iqp1\boxed{i\le q\le p-1}

    の範囲にある。

  2. p<kp<k のとき、kk 番目に小さい自然数は

    p+1qj\boxed{p+1\le q\le j}

    の範囲にある。

[4]

空欄は次の通りである。

空欄解答
(ア)p=kp=k
(イ)A[p]A[p]
(ウ)p>kp>k
(エ)k_th(A,i,p-1,k)
(オ)p<kp<k
(カ)k_th(A,p+1,j,k)

したがって、完成した手続きは

手続き k_th(A,i,j,k)

1. p に partition(A,i,j) の返り値を代入する。
2. もし p = k であれば、A[p] を返す。
3. もし p > k であれば、k_th(A,i,p-1,k) を返す。
4. もし p < k であれば、k_th(A,p+1,j,k) を返す。

となる。ここで kk は配列全体における順位であり、再帰呼出しでもインデックスを保持するため、右側を探索するときも kpk-p などへ変換する必要はない。