Python
 Computer >> コンピューター >  >> プログラミング >> Python

Pythonで2進数表現における最長の連続する1を見つけるプログラム

問題の概要

負でない整数 n が与えられたとき、その2進数表現の中に現れる「1」が連続して並んでいる区間のうち、最も長いものの長さを求めることを考えます。

例として、入力が n = 1469 の場合を見てみましょう。1469 を2進数に変換すると「10110111101」となり、この中には「1」が4個連続して並んでいる箇所が存在します。したがって、出力は 4 となります。

解法のアプローチ

この問題は、ビット演算を活用することで非常にエレガントに解くことができます。手順は以下の通りです。

  • カウント用の変数 count を 0 で初期化します。
  • n が 0 になるまで、次の処理を繰り返します。
    • n := n AND(n を1ビット左シフトした値)
    • count := count + 1
  • 最後に count を返します。

なぜこの方法が有効なのかというと、「n & (n << 1)」という操作によって、隣り合う2つのビットがどちらも1である位置だけが残るためです。つまり、ループを1回実行するごとに、連続する「1」の列の長さが1ずつ短くなっていきます。その結果、最初に存在していた最長の連続「1」の長さと同じ回数だけループが実行され、それがそのまま答えになります。

Pythonでの実装例

理解を深めるために、実際のコードを見てみましょう。

def solve(n):
    count = 0
    while n != 0:
        n = n & (n << 1)
        count = count + 1

    return count

n = 1469
print(solve(n))

入力

1469

出力

4

計算量の評価

このアルゴリズムの時間計算量は O(log n) です。各ループの実行ごとに連続する「1」の長さが少なくとも1ずつ減少し、ループの回数は n のビット長(およそ log₂n)を超えないためです。また、追加のメモリをほとんど必要としないため、空間計算量は O(1) と非常に効率的です。ビット演算のみで構成されているため、文字列変換などを用いる方法よりも高速に動作する点も大きなメリットといえます。

  1. Pythonで二分木の根から葉までの最長経路の合計値を求めるプログラム

    二分木が与えられたとき、根(ルート)から葉ノードまでの最長経路におけるノード値の合計を求める問題を考えます。同じ長さの経路が複数存在する場合は、その中で合計値が大きい方の経路を採用します。たとえば、次のような二分木が入力として与えられた場合を考えてみましょう。この場合、出力は 20 になります。解き方のアプローチこの問題は、再帰を使って各ノードから「深さ」と「合計値」のペアを返すことで解けます。手順は以下の通りです。関数 rec() を定義します。引数として現在のノード curr を受け取ります。curr が null(空)の場合は、ペア (0, 0) を返します。bigger := 左の子に

  2. 【Python】二分木で偶数値のみからなる最長パスを求めるアルゴリズムと実装

    問題概要 二分木が与えられたとき、木の中の任意の2つのノードをつなぐ経路のうち、偶数の値のみで構成される最長のパスの長さを見つけることを考えます。 例えば、次のような二分木が入力として与えられた場合を考えてみましょう。 この場合、最長のパスは [10, 2, 4, 8, 6] となるため、出力は 5 になります。 解法のアプローチ この問題は、再帰的な深さ優先探索(DFS)を使うことで効率的に解くことができます。各ノードについて「左部分木から伸びる偶数パスの長さ」と「右部分木から伸びる偶数パスの長さ」を求め、それらを組み合わせて全体の答えを更新していくのがポイントです。 具体的には、以下の