C++で桁を並べ替えて2の累乗にできるか判定するアルゴリズム
正の整数 N が与えられたとします。この数の桁を任意の順序に並べ替え(元の順序も含む)、先頭の桁が 0 以外になるようにします。そのうえで、並べ替えた結果が 2 の累乗になるような並べ方が存在するかどうかを判定します。たとえば、数値が 46 の場合、答えは true となります。
解法の考え方
この問題は、以下の手順に従って解くことができます。
countというメソッドを定義します。引数として x を受け取ります。ret := 0 で初期化します。
x が 0 でない間、次の処理を繰り返します。
ret := ret + 10 ^ (x の最下位桁)
x := x / 10
ret を返します。
メインの処理では、以下を実行します。
x := count(N) を計算します。
i を 0 から 31 までループさせます。
count(2^i) == x であれば true を返します。
どれとも一致しなければ false を返します。
ここで使われる count 関数は、各桁の数字 d に対して 10d を加算していくことで、その数値の「桁構成のシグネチャ」を生成します。同じ数字の組み合わせ(マルチセット)を持つ数値同士は必ず同じシグネチャになるため、N のシグネチャと 2 の累乗(20 〜 231)のシグネチャを比較するだけで、桁の並べ替えによって一致させられるかどうかを高速に判定できます。
理解を深めるために、以下の実装例を見てみましょう。
実装例(C++)
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
int count(int x){
int ret = 0;
while(x){
ret += pow(10, x % 10);
x /= 10;
}
return ret;
}
bool reorderedPowerOf2(int N) {
int x = count(N);
for(int i = 0; i < 32; i++){
if(count(1 << i) == x) return true;
}
return false;
}
};
main(){
Solution ob;
cout << (ob.reorderedPowerOf2(812));
}
入力
812
出力
1
この例では、812 の桁を並べ替えると 128(= 27)を作ることができるため、出力は 1(true)となります。count の呼び出しはそれぞれ桁数に比例したコストしかかからず、比較対象も 20 から 231 までの 32 個だけなので、全体の計算量は O((log N)2) 程度に抑えられ、非常に効率的な手法といえます。
-
C++で数値の累乗を計算する方法:再帰・非再帰プログラムの実装例
数の累乗とは数の累乗は x^y の形式で表され、x は基数(底)、y は指数を表します。例を見てみましょう。x = 2、y = 10 の場合 x^y = 1024 ここで、x^y は 2^10 を意味します数の累乗は、再帰的プログラムと非再帰的プログラムの2つの方法で計算できます。以下、それぞれの実装方法を詳しく解説します。非再帰プログラムによる累乗の計算まずは、forループを使用した非再帰的なプログラムの例です。サンプルコード#include<iostream>using namespace std;int power(int x, int y) { int i
-
Pythonで桁を並べ替えて2の累乗を作れるか判定するプログラム
正の整数 N が与えられたとします。この数の桁を任意の順序に並べ替え(元の順序のままでも可)、先頭の桁が0にならないようにします。そして、その結果得られる数が2の累乗になるようにできるかどうかを判定する必要があります。例えば、入力が N = 812 の場合、出力は True となります。これは「812」の桁を並べ替えると「128」(= 27)を作れるためです。解法のアプローチこの問題を解く鍵となるのは、「桁を並べ替えた数同士は、ソート後の桁の並びが必ず一致する」という性質です。つまり、ある数がNの桁を並べ替えたものであるかを調べるには、両者を文字列に変換して文字をソートし、一致するかどうかを比