マツシタのお勉強

'a'と'b'でパターンマッチ

問題

文字列wordとパターンを表すpatternが入力値として与えれる。patternは'a'と'b'のみで構成されている。wordがpatternにマッチするか否かを求める問題。

word = “catcatgocatgo”, pattern = “abbab”
a -> cat
b -> go
とすればwordはpatternにマッチすることができるのでtrueを返す。

解法

wordの先頭から1文字ずつaに変換する。

a -> c

a -> ca

a -> cat

といった具合だ。aが決まるとbが決定する。これは、pattern = “abbab"の中のabそれぞれの出現回数とwordのlengthによって求めることができる。aとbが決定したらpatternにそって文字列を生成し、wordと一致するかをチェックしてあげれば良い。

計算量

wordのサイズをNとすると、aを決定するためにO(N)。bはO(1)で決定し、aとbの部分文字列を生成するための処理と、patternを元に候補となる文字列を生成し比較する処理がそれぞれO(N)(これらはネストではない)ので空間計算量はO(N2)となる。

ソースコード

平面上のN個の点を最も多く通る線を見つける

問題

xy平面上にN個の点が与えられる。最も多くの点を通るように直線を引いた時の点の最大値を求める問題

leetcode.com

解法

HashMapを用いることでO(N2)で解くことができる。forループを2回使い2つの点を全列挙する。2つの点のを結ぶ傾きをキーとして、HashMapに保存する。バリューには1つの座標を固定した時に、傾きが同じ値になるものの出現回数を保存する。

傾きを比較するために小数値ではなく分数で扱う。

少数値を比較するためには誤差を考慮する必要があるので、分数のまま扱うことにする。分母と分子をプロパティとして持つクラスを定義してあげる。 分数を作る際に、約分できる時は約分をする。約分するためにユークリッドの互除法を用いて最大公約数を計算する

keita-matsushita.hatenablog.com

分母がゼロになる時を注意する

傾きを計算する時に、2つの点のx座標が等しいと分母が0となってしまい傾きがINFとなる。この時は、Lineクラスに傾きがINFか否かをチェックするためのプロパティを用意し場合分けに使う

同一点を考慮する

入力値として与えられる点は、全く同じ座標のものも含まれる。よって同一座標の数をカウント(dup)することで対応する。

コード

階乗のゼロ Cracking the Coding the Interview

問題

整数Nが与えら、Nの階乗を計算した時に、末尾に連なる0の数を求める問題。

解き方

どんな時に末尾に0が来るか考える。階乗の計算では足し算はなく掛け算のみなので、10を掛けた時に末尾に0がつく。また、10は2×5なので2と5を掛けた回数分、0が着くことが分る。また、5を掛ける回数は2を掛ける回数に比べ多いので、5を掛ける回数を数えれば良い。


N = 10の時
階乗は1×2×3×4×5×6×7×8×9×10

上記で5を掛けているのは2回(5, 10)なので末尾には0が2つ着く。これはN / 5で求められる。また、25を掛けた場合を考えると、5を2回掛けている事が分る。よってコードは以下のようになる。

JavaのCollectionsクラスのshuffleメソッドの実装を覗く

はじめに

リストをランダムに入れ替える方法を考える時にどのようにするのが実装するのがベストなのか疑問に思い、JavaのCollectionsに定義されているshuffleメソッドの実装を見てみる。

Collections.shuffle

上記のコードで実際にランダム化している箇所は以下の部分である。

リストの後ろの要素と乱数によって得たインデックスの要素をスワップしている。これを範囲を上手く調整しながらN回繰り返している。 とてもシンプルな実装で且つ計算量もO(N)とリーズナブルだ。