本来なら、計算量O(NlogN)で済むところを、数弱の頭でなんとか考えた挙句O(2^N)という最悪の計算量でLISを求め可視化して見ました。
グラフを見ると簡単ですが、実際にアルゴリズムを作るとなると手間がかかりました。
目次
LISとは
LISとはLongest increasing Subsequence の略であり、日本語では最長増加部分列というそうです。
l_n = [51, 4, 11, 8, 41, 90]
という配列があったとします。
この場合のLISは
4 8 41 90
4 11 41 90
の二つになります。
これをmatplotlibを用いてグラフにしてみると、
from matplotlib import pyplot as plt
n_l = [51, 4, 11, 8, 41, 90]
fig = plt.figure()
x = [i for i in range(len(n_l))]
y = [int(i) for i in n_l]
plt.scatter(x,y)
plt.xlabel('x')
plt.ylabel('y')
put.imshow()
以下のようになります。
このグラフの中で自身より右側にあり、かつ大きいプロットを辿っていった線のうち一番多くの点を含むものがLISとなります。
今回のl_nにはLISが二つあるので、2つ折れ線グラフができます。
数が増えた場合
例えば、8000個くらいのランダムな数を生成し、n_lにリストとして代入するとします。
import random
n_l = [random.randint(1, 8071) for i in range(8070)]
これをグラフにプロットしてみると、以下のようになります。
fig = plt.figure()
x = [i for i in range(len(n_l))]
y = [int(n_l[i]) for i in range(len(n_l))]
plt.scatter(x,y,s = 1)
plt.xlabel('x')
plt.ylabel('y')
fig.savefig('img_3.jpg',dpi=500)
途方もない数の点の中から、一番多く結べる右上がりの線を見つけ出すのは難しそうですね。
計算量がO(2^n)になってしまいますが、網羅的に配列を見ていくと以下のような結果が現れます。
ちゃんと右上がりのプロットになっていますね。
しかし、現実的ではないので、次回は計算量をO(n^2)まで落とせるDPで解いてみようと思います。