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

C++で重みが2の累乗となる木のノードを数える方法


各ノードに「重み」が割り当てられた二分木が与えられます。この記事の目的は、重みが2の累乗(べき乗)になっているノードの個数を求めることです。たとえば重みが32であれば 32 = 25 なので、このノードはカウントの対象となります。

入力例1

入力した値から生成される木は次のようになります。

C++で重みが2の累乗となる木のノードを数える方法

出力

与えられた木のうち、重みが2の累乗であるノードの数: 3

説明

木の各ノードと、それぞれに対応する重みが与えられています。そこで、すべての重みについて「2の累乗として表せるかどうか」を順に判定していきます。

ノード重み2の累乗での表現判定
282 × 2 × 2 = 23はい
1100表現不可いいえ
4211素数のため表現不可いいえ
31624はい
87171表現不可いいえ
9322 × 2 × 2 × 2 × 2 = 25はい

入力例2

別の入力値から生成される木は次のようになります。

C++で重みが2の累乗となる木のノードを数える方法

出力

与えられた木のうち、重みが2の累乗であるノードの数: 2

説明

同様に、各ノードの重みが2の累乗かどうかを確認します。

ノード重み2の累乗での表現判定
21624はい
1141表現不可いいえ
441素数のため表現不可いいえ
36426はい
88134(2の累乗ではない)いいえ

プログラムで使用するアプローチ

このアプローチでは、木に対してDFS(深さ優先探索)を適用して全ノードを走査し、各ノードの重みが2の累乗かどうかを判定します。そのために、Node_Weight(100) と edge_graph[100] という2つのvectorを用意します。

  • Node_Weight[] を各ノードの重みで初期化します。
  • vector の edge_graph を使って木(グラフ)を構築します。
  • グローバル変数 powers を宣言し、0で初期化します。
  • 関数 power_two(int node, int root) は、現在のノードとその親ノードを受け取り、重みが2の累乗であるノードの数をカウントします。
  • set = Node_Weight[node] として、現在のノードの重みを取得します。
  • set && (!(set & (set - 1))) が真であれば、その値は2の累乗です。これはビットごとのANDと否定を組み合わせた定番の判定方法で、正の整数 x について x & (x-1) が0になるのは x が2の累乗の場合だけです。
  • 条件を満たした場合、set の値が2の累乗であるため powers をインクリメントします。
  • forループで edge_graph[node] 内の隣接ノードを走査します。
  • ベクトル内の次のノードに対して power_two(it, node) を再帰的に呼び出します。
  • すべての再帰呼び出しが完了した時点で、powers には重みが2の累乗であるノードの総数が格納されています。

サンプルコード

#include <bits/stdc++.h>
using namespace std;
vector<int> Node_Weight(100);
vector<int> edge_graph[100];
int powers = 0;
void power_two(int node, int root){
    int set = Node_Weight[node];
    if(set && (!(set & (set - 1)))){
        powers++;
    }
    for(int it : edge_graph[node]){
        if(it == root){
            continue;
        }
        power_two(it, node);
    }
}
int main(){
    // 各ノードの重み
    Node_Weight[2] = 8;
    Node_Weight[1] = 100;
    Node_Weight[4] = 211;
    Node_Weight[3] = 16;
    Node_Weight[8] = 7171;
    Node_Weight[9] = 32;
    // グラフの辺を作成
    edge_graph[2].push_back(1);
    edge_graph[2].push_back(4);
    edge_graph[4].push_back(3);
    edge_graph[4].push_back(8);
    edge_graph[8].push_back(9);
    power_two(2, 2);
    cout<<"与えられた木のうち、重みが2の累乗であるノードの数: "<<powers;
    return 0;
}

出力

上記のコードを実行すると、次の出力が得られます。

与えられた木のうち、重みが2の累乗であるノードの数: 3
  1. C++で二分木の指定した2つのレベル間にあるすべてのノードを出力する方法

    この問題では、二分木と、木の中の2つのレベル(上位レベルと下位レベル)が与えられ、その2つのレベル間に存在するすべてのノードを出力することが求められます。二分木とは、各ノードが最大2つの子ノード(0個・1個・2個)を持つ特殊な木構造のことです。問題の例具体例を使って問題を理解しましょう。上位レベル(upper):3下位レベル(lower):1出力結果:6 3 9 7 4 8 10解決アプローチ方法1:再帰関数を使う方法この問題を解くには、指定されたレベルのノードを出力する必要があります。upperからlowerまでのレベルをループで回しながら、再帰関数を呼び出すことで実現できます。このアルゴリ

  2. C++で完全二分木の全ノードの合計を効率的に求める方法

    問題の概要 正整数 L が与えられ、これは完全二分木(パーフェクト・バイナリツリー)のレベル数を表しているとします。この木の葉ノードには、1 から n までの番号が順に割り当てられています(n は葉ノードの総数)。また、各親ノードの値は、その 2 つの子ノードの値の合計となります。 今回の課題は、この完全二分木に含まれるすべてのノードの値の合計を出力するプログラムを作成することです。 例として、次のような木を考えてみましょう。 この木の場合、すべてのノードの合計は 30 になります。 解法のアプローチ この問題を注意深く観察すると、求めるべきは全ノードの値の総和です。葉ノードには 1 から