問題にチャレンジして、ユーザー同士で解答を教え合ったり、コードを公開してみよう!
クイックソートは、ピボットと呼ばれる値を1つ選び、それを基準としてデータ列を「ピボット未満の要素からなるデータ列」と「ピボット以上の要素からなるデータ列」に二分すること
を再帰的に行うアルゴリズムです。このアルゴリズムは、問題を小さな問題に分割して解くことを繰り返すことによって元の問題の答えを得る手法である「分割統治法」に基づいており、実用的なソートアルゴリズムの中で最も高速であるとされています (名前に quick と付いていることからも、その高速さが評価されていることが窺えます)。
ピボットの選び方にはいくつか種類があり、
・データ列の先頭をとる
・データ列の末尾をとる
・データ列からランダムにとる
・データ列からランダムに2つとり、その中央値をとる
// アルゴリズムが正しく実装されていることを確認するために導入するカウンタ変数、ソート処理には関係がないことに注意
count <- 0
/**
A[left] ~ A[right-1] をクイックソートする
配列 A をクイックソートするには quick_sort(A, 0, n) を呼び出す
*/
quick_sort(A : 配列, left : 整数, right : 整数)
// ソートする範囲の長さが1以下の場合は何もしない
if left+1 >= right then
return
// データ列の末尾 A[right-1] をピボットとする
pivot <- A[right-1]
// ピボット未満のデータを挿入する位置を保持する変数を用意
cur_index <- left
for i = left to right-2
if A[i] < pivot then
swap(A[cur_index], A[i])
cur_index++
count++
// ピボットを A[cur_index] へ移動し、データ列を分割する
swap(A[cur_index], A[right-1])
// 分割されたデータ列に対して再帰的にクイックソートを行う
quick_sort(A, left, cur_index)
quick_sort(A, cur_index+1, right)
count
の値を出力してください。
n
A_1 A_2 ... A_n
2行出力してください。
1行目に、ソート後の数列 A' の各要素を半角スペース区切りで出力してください。
2行目に、count
を出力してください。
また、末尾に改行を入れ、余計な文字、空行を含んではいけません。
A'_1 A'_2 ... A'_n
count
すべてのテストケースにおいて、以下の条件をみたします。
・ 1 ≦ n ≦ 500,000
・ -1,000,000,000 ≦ A_i ≦ 1,000,000,000 (1 ≦ i ≦ n)
10
7 6 10 2 5 1 8 3 9 4
1 2 3 4 5 6 7 8 9 10
9