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

C++で配列内に合計値が存在する個別のペアの数をカウントする方法

整数値からなる任意のサイズの配列 arr[] が与えられたとき、「その和も同じ配列内に存在する」個別のペアの数を計算するのが本記事のテーマです。

配列とは、同じ型の要素を固定サイズで連続的に格納できるデータ構造の一種です。データの集合を保持するために使われますが、実用上は「同じ型の変数の集まり」として捉えると理解しやすいことが多いでしょう。

押さえておくべきポイント

  • ペアは要素の並び順にかかわらず、同じ組み合わせであれば1回のみカウントします。たとえば (3,2) と (2,3) は同一のペアとして1件と数えます。
  • 配列内に複数回現れる値は、ペアを構成するうえでちょうど2つぶんまでしか考慮されません。たとえば配列の要素が {2, 2, 2, 2} の場合、成立するペアは (2,2) のみで、カウントは1となります。

具体例

入力 − int arr = {6, 4, 10, 14}
出力 − count is 2

解説 − 和が配列内に存在するペアは (6,4) と (10,4) の2つなので、カウントは2になります。

入力 − int arr = {6, 6, 6, 6, 6, 13}
出力 − count is 0

解説 − 和が同じ配列内に存在するペアがひとつもないため、カウントは0になります。

プログラムで採用しているアプローチ

  • まず配列 arr[] を作成します。
  • sizeof(ar) / sizeof(ar[0]) を使い、配列の長さ(要素数 n)を求めます。
  • 各要素の出現回数を記録するためのマップ mymap を用意します。(ar[i]) + (sum − ar[i]) = sum の関係を利用することで、ペア候補を効率的に判定できます。
  • i を 0 から配列サイズ未満の範囲でループさせます。
  • 重複ペアの除外用に、pair 型をキーにもつもうひとつのマップ p を作成します。
  • 外側のループ内で、j を i+1 から配列サイズ未満の範囲でループさせます。
  • ループ内では、mymap[ar[i] + ar[j]] > 0 かつ p[{ar[i], ar[j]}] == 0 を満たす場合に限り、result を 1 増やします。
  • p[{ar[i], ar[j]}]p[{ar[j], ar[i]}] をそれぞれインクリメントし、順序が逆になるだけの重複登録を防ぎます。
  • 最後に result を返却し、main 関数で結果を出力します。

サンプルコード

#include <iostream>
#include <map>
using namespace std;

// ar[0..n-1] の中から、和が配列内に存在する
// ペアの総数を返す関数
int countpairs(int ar[], int n){
    // すべての要素の出現回数をマップ mymap に記録。
    // (ar[i]) + (sum - ar[i]) = sum の関係から
    // ペア (ar[i], sum-ar[i]) を見つけやすくする。
    map<int, int> mymap;
    for (int i = 0; i < n; i++){
        mymap[ar[i]]++;
    }
    // 重複項目を除外するために結果用マップを使用
    map<pair<int, int>, int> p;
    int result = 0;
    // すべてのペアを走査
    for (int i = 0; i < n; i++){
        for (int j = i + 1; j < n; j++){
            // 現在のペアの和が配列内に存在する場合
            if (mymap[ar[i] + ar[j]] > 0 && p[{ ar[i], ar[j] }] == 0){
                result++;
            }
            // 重複を避けるため、現在のペアを両方向で登録
            p[{ ar[i], ar[j] }]++;
            p[{ ar[j], ar[i] }]++;
        }
    }
    return result;
}

// main関数
int main(){
    int ar[] = { 6, 4, 10, 14 };
    int n = sizeof(ar) / sizeof(ar[0]);
    cout << "count is " << countpairs(ar, n);
    return 0;
}

出力結果

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

count is 2
  1. C++でXとの合計がフィボナッチ数になるノードを数える方法

    各ノードに数値の重みが割り当てられた二分木が与えられます。この記事の目的は、「ノードの重み + X」の計算結果がフィボナッチ数となるノードの個数を求めることです。フィボナッチ数列とは、0, 1, 1, 2, 3, 5, 8, 13… のように続く数列で、n番目の数は(n−1)番目と(n−2)番目の数の和になります。たとえば重みが13であればフィボナッチ数に該当するため、そのノードはカウント対象となります。入力例1temp = 1 の場合。値を入力すると、以下のような木が構成されます。出力Count the nodes whose sum with X is a Fibonacci number

  2. C++で配列内の「割り切れるペア」の数を数える方法

    本記事では、任意のサイズの整数型要素を持つ配列が与えられたとき、その中から「一方の要素がもう一方の要素を割り切れる」ようなペア(整除ペア)の総数を求める方法を解説します。 配列とは、同じ型の要素を固定サイズで連続的に格納できるデータ構造の一種です。複数のデータをまとめて管理するために使われますが、「同じ型の変数の集まり」と捉えたほうが理解しやすい場合も多いでしょう。 具体例 入力:int arr[] = {1, 2, 3, 6} 出力:count is 4 説明:(1,2)、(1,3)、(1,6)、(3,6) の4つのペアにおいて、一方の要素が他方の要素を割り切れます。1はあらゆる整数を割り