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

Pythonで同じセットビット数を持つ次に大きい数を見つけるプログラム

数値 n が与えられたとき、2進表現における1の個数(セットビット数)が n と同じで、かつ n より大きい最小の数を求める問題を考えます。

例えば、入力が n = 7 の場合、出力は 11 になります。7 を2進数で表すと「0111」ですが、1が3つという条件を保ったまま 7 より大きい最小の数は、2進数で「1011」、すなわち10進数の 11 だからです。

解法のアプローチ

この問題はビット操作を利用することで効率的に解けます。手順は以下の通りです。

  • copy に n を代入し、zeros と ones を 0 で初期化します。

  • copy が 0 ではなく偶数である間、次の処理を繰り返します。

    • zeros を 1 増やす

    • copy を 1 ビット右シフトする(copy / 2 と同等)

  • copy が奇数である間、次の処理を繰り返します。

    • ones を 1 増やす

    • copy を 1 ビット右シフトする(copy / 2 と同等)

  • right := ones + zeros とします。

  • n := n OR (2^right) — right 番目のビットを 1 にセットします。

  • n := n AND NOT((2^right) − 1) — right より下位のビットをすべてクリアします。

  • n := n OR ((2^(ones − 1)) − 1) — 下位 ones − 1 ビットをすべて 1 にセットします。

  • n を返します。

仕組みのポイント

このアルゴリズムの核心は、2進表現の中で最も右側にある「01」というパターンを「10」へ入れ替える点にあります。こうすることで、1の総数を変えずに数を大きくできます。その後、残りの1を可能な限り下位のビットへ寄せることで、「同じ1の個数を持ちながら、元の数より大きい最小の数」が得られます。

計算量はビット長に比例する O(log n) となり、全ての候補を順に調べる方法よりもはるかに効率的です。

実装例

class Solution:
    def solve(self, n):
        copy = n
        zeros = 0
        ones = 0
        while copy and not copy & 1:
            zeros += 1
            copy >>= 1
        while copy & 1:
            ones += 1
            copy >>= 1
        right = ones + zeros
        n |= 1 << right
        n &= ~((1 << right) - 1)
        n |= (1 << ones - 1) - 1
        return n

ob = Solution()
n = 7
print(ob.solve(n))

入力

7

出力

11
  1. Pythonで同じラベルを持つサブツリー内のノード数を求めるプログラム

    ここでは、n個のノードからなる根付きの一般木を考えます。ノードには0からn-1までの番号が振られており、各ノードには小文字の英字ラベルが割り当てられています。ラベルは配列labelsとして与えられ(labels[i]がi番目のノードのラベル)、木は辺リストで表現されます。各辺eは[u, v]という形式で、uが親、vが子であることを意味します。 求めたいのは、サイズnの配列Aです。A[i]には「i番目のノードと同じラベルを持つ、そのサブツリー内のノードの総数」を格納します。 例えば、入力が次のような場合を考えてみましょう。 n = 5、label = ccaca のとき、出力は [3, 2,

  2. Pythonでリスト内の最大値を見つける方法|sort()とmax()の2つのアプローチ

    この記事では、リストの中から最大の数値を見つけるための解決策とアプローチについて詳しく解説します。問題の概要数値のリストが与えられたとき、その中から最大の要素を見つけ出す必要があります。Pythonでは、主に以下の2つの方法でこれを実現できます。ソート(並べ替え)を利用する方法組み込み関数 max() を利用する方法アプローチ1:sort() 関数を使う方法リストを sort() メソッドで昇順に並べ替えると、リストの最後の要素(インデックス -1)が必ず最大値になります。サンプルコードlist1 = [18, 65, 78, 89, 90] list1.sort() # メイン処理 prin