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

C++でビットを再配置して最大の数を作る方法

問題文

符号なし整数が与えられたとき、その数が持つビットを並べ替えて作ることができる最大の数を求めます。

たとえば、入力が 8 の場合、その2進数表現は次のようになります。

00000000000000000000000000001000

この数を最大化するには、最上位ビット(MSB)を1にします。すると数は 2147483648 となり、その2進数表現は次のとおりです。

10000000000000000000000000000000

アルゴリズム

  1. 与えられた数の2進数表現におけるセットビット(1になっているビット)の個数 n を数える
  2. 下位 n ビットがすべて1になる数を作る
  3. その数を (32 − n) ビットだけ左にシフトする

この手順により、1になっているビットがすべて最上位側に集められ、32ビットで表現できる最大の数が得られます。

実装例(C++)

#include <bits/stdc++.h>
using namespace std;
unsigned getMaxNumber(unsigned num){
    int n = __builtin_popcount(num);
    if (n == 32) {
        return num;
    }
    unsigned result = (1 << n) - 1;
    return (result << (32 - n));
}
int main(){
    unsigned n = 8;
    cout << "Maximum number = " << getMaxNumber(n) << endl;
    return 0;
}

コードのポイント

  • __builtin_popcount(num):GCCやClangで利用できる組み込み関数で、引数の整数に含まれる1のビット数を返します。
  • (1 << n) - 1:下位 n ビットがすべて1の数(例:n=4なら 1111)を生成します。
  • すべての32ビットがすでに1の場合(n=32)は、これ以上大きくできないため元の値をそのまま返します。

出力

上記のプログラムをコンパイルして実行すると、次の出力が得られます。

Maximum number = 2147483648
  1. C++で配列の中央値を最大化する方法を解説

    問題の概要N個の要素を含む配列 arr[] と整数 K(K < N)が与えられます。求められているのは、この配列にK個の整数要素を挿入し、結果として得られる配列の中央値を最大化することです。例として、入力配列が {1, 3, 2, 5}、k = 3 の場合を考えてみましょう。配列をソートすると {1, 2, 3, 5} になります最大値の5より大きい要素を3つ挿入します。この操作により、配列は {1, 2, 3, 5, 6, 6, 6} になります新しい配列の中央値は 5 となりますアルゴリズムの考え方この問題を解くためのポイントは、以下の2点です。挿入する要素の選び方: 中央値を最大化

  2. C++でk個のセットビットを持つ数を最大化するために必要な最小フリップ回数

    問題文2つの整数 n と k が与えられます。n のビットを反転(フリップ)して、結果の数がちょうど k 個のセットビット(値が1のビット)を持ち、かつ取り得る最大の数になるようにするために必要な、最小のフリップ回数を求めてください。なお、入力は「k が n のビット数より小さい」という条件を満たす必要があります。例n = 9、k = 2 とします。9 の2進表現は 1001 であり、4ビットで構成されています。4桁の2進数の中でセットビットが2個となる最大の数は 1100、すなわち10進数の 12 です。1001 を 1100 に変換するには、2ビットを反転する必要があります。アルゴリズム1