マツシタのお勉強

平面上の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)とリーズナブルだ。

LinkedListが回文になっているか否かを判定 Palindrome Linked List in LeetCode

問題

leetcode.com

解法

通常の速さと、その2倍の速さでLinkedListを探索していくと、早いほうが末尾に到着する時に遅い方はちょうど中間地点にいる。 中間地点まできたら、そこから末尾まで進むと同時にリストを逆順にしていく。 ここまでの操作で、リストの後半の部分がひっくり返った状態で得られるので、あとはリストの前半部分と数値が一致するかを見ていく。

ソースコード