まじめに理屈を考えるのには時間がかかるので、手抜きをして実験的にやってみました。
Angela_Nakasugiさんのコードを修正して、リストを与えると、それの再帰呼び出しの回数と結果を返す関数を作りました。
python
1def simple_qsort(lst):
2 if len(lst) <=1:
3 return 1, lst
4 pivot =lst[0]
5 lst1 =[x for x in lst if x < pivot]
6 lst2 =[x for x in lst if x == pivot]
7 lst3 =[x for x in lst if x > pivot]
8 n1, sq1 = simple_qsort(lst1)
9 n3, sq3 = simple_qsort(lst3)
10 return n1+n3+1, sq1 + lst2 + sq3
実行例
python
1>>> print(simple_qsort([10,2,6,1,3,4,5,8,7,9]))
2(13, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
次に、長さがlengthのリストを与えた時にその順列のそれぞれに対して再帰呼び出しの回数を計算して分類する関数を作ってみました。
戻り値は辞書で、再帰呼び出しの回数をキーとして、値はその回数となる順列のリストです。
python
1import itertools
2
3def count_qs(length):
4 counter = {}
5 for lst in itertools.permutations(list(range(1, length+1))):
6 n, sq = simple_qsort(lst)
7 if n in counter:
8 counter[n].append(lst)
9 else:
10 counter[n] = [lst]
11 return counter
結果が長くなって読みにくいので、リストを値として持つ辞書に対して、同じキーに対して値のリストの長さを返す関数を作りました。
python
1def counter_count(counter):
2 return {key: len(counter[key]) for key in counter}
実行例
python
1>>> counter_count(count_qs(5))
2{9: 16, 7: 88, 5: 16}
これは、[1,2,3,4,5]の順列を並べ替えるときの再帰呼び出しの回数が9となる順列は16通り、7となる順列は88通り、5となる順列は16通りであることを示しています。
2から8までの結果を並べてみると以下になります。
python
1>>> counter_count(count_qs(2))
2{3: 2}
3>>> counter_count(count_qs(3))
4{5: 4, 3: 2}
5>>> counter_count(count_qs(4))
6{7: 8, 5: 16}
7>>> counter_count(count_qs(5))
8{9: 16, 7: 88, 5: 16}
9>>> counter_count(count_qs(6))
10{11: 32, 9: 416, 7: 272}
11>>> counter_count(count_qs(7))
12{13: 64, 11: 1824, 9: 2880, 7: 272}
13>>> counter_count(count_qs(8))
14{15: 128, 13: 7680, 11: 24576, 9: 7936}
ここから、10の場合にはもっとも多い再帰呼び出しの回数が19でもっとも多い再帰呼び出しの回数が11となることが予想されます。
この予想が正しいとして、19と11となるリストを一つ出せるようにcount_qsを少し改造した以下の関数を作りました。
python
1def count_qs_sample(length, m):
2 counter = {}
3 for lst in itertools.permutations(list(range(1, length+1))):
4 n, sq = simple_qsort(lst)
5 if n == m:
6 return lst
7
これを使って実行してみると、
python
1>>> count_qs_sample(10,19)
2(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
3>>> count_qs_sample(10,11)
4(1, 3, 2, 5, 4, 7, 6, 9, 8, 10)
あとは、「10の場合にはもっとも多い再帰呼び出しの回数が19でもっとも多い再帰呼び出しの回数が11となることが予想されます。」は数値的には以下のように証明できています。
python
1>>> counter_count(count_qs(10))
2{19: 512, 17: 128512, 15: 1304832, 13: 1841152, 11: 353792}
しかし、一般化するためにはちゃんと説明する論理が必要ですね。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/10/18 07:04