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

【C++】合計が指定した値に等しい2つの連結リストのペアを数える方法

2つの連結リストが与えられ、それぞれのリストに含まれる整数要素を組み合わせて、合計が指定した値(k)と等しくなるペアが何組作れるかを数えるのが本記事の課題です。連結リスト(linked list)とは、複数のデータ構造がリンク(ポインタ)で順々に接続されたデータ構造の列のことです。

入出力の確認

例1

vector<int> v_1 = {5, 7, 8, 10, 11};
vector<int> v_2 = {6, 4, 3, 2, 0};
int k = 11;

出力:

合計がkに等しいペアの個数: 4

解説: 2つのリストから作れる全25通りの組み合わせのうち、合計が11に一致するのは (5, 6)、(7, 4)、(8, 3)、(11, 0) の4組です。

例2

vector<int> v_1 = {2, 3, 5, 6};
vector<int> v_2 = {6, 4, 3};
int k = 6;

出力:

合計がkに等しいペアの個数: 2

解説: 全12通りの組み合わせのうち、合計が6に一致するのは (2, 4) と (3, 3) の2組です。

プログラムのアプローチ

  • kの値と整数値を2つのvectorに入力し、それらをもとに連結リストを構築できるようにします。
  • 引数として渡されたvectorから連結リストを作成する関数を作ります。
    • vectorのサイズ分だけループを回し、ListNodeクラスのポインタオブジェクトを作成します。
    • ptr->next がNULLでない間は ptr = ptr->next としてリスト末尾まで辿ります。
    • ptr->next に新しいノード(vector[i])を設定します。
    • 先頭ポインタstartを返します。
  • 指定した合計に一致するペアの個数を返す関数を作ります。
    • カウント用の一時変数countを0で初期化します。
    • *first_list(1つ目のリスト用)と *second_list(2つ目のリスト用)という2つのポインタオブジェクトを用意します。
    • 外側のループで1つ目のリストを先頭から末尾まで走査します。
    • 内側のループで2つ目のリストを先頭から末尾まで走査します。
    • (first_list->data + second_list->data) == k が成立したらcountを1増やします。
    • 最後にcountを返します。
  • 結果を出力します。

この手法はすべてのペアを総当たりで調べる方法で、時間計算量はO(n × m)(n, mは各リストの長さ)となります。

C++実装例

#include<bits/stdc++.h>
using namespace std;

class ListNode {
public:
    int data;
    ListNode *next;
    ListNode(int data) {
        this->data = data;
        next = NULL;
    }
};

// vectorから連結リストを作成する関数
ListNode *CreateList(vector<int> v) {
    ListNode *start = new ListNode(v[0]);
    for (int i = 1; i < v.size(); i++) {
        ListNode *ptr = start;
        while (ptr->next != NULL) {
            ptr = ptr->next;
        }
        ptr->next = new ListNode(v[i]);
    }
    return start;
}

// 合計がkに等しいペアの個数を数える関数
int sum_pair(ListNode *start_1, ListNode *start_2, int k) {
    int count = 0;
    ListNode *first_list, *second_list;
    for (first_list = start_1; first_list != NULL; first_list = first_list->next) {
        for (second_list = start_2; second_list != NULL; second_list = second_list->next) {
            if ((first_list->data + second_list->data) == k) {
                count++;
            }
        }
    }
    return count;
}

int main() {
    vector<int> v_1 = {5, 7, 8, 10, 11};
    ListNode* start_1 = CreateList(v_1);
    vector<int> v_2 = {6, 4, 3, 2, 0};
    ListNode* start_2 = CreateList(v_2);
    int k = 11;
    cout << "合計がkに等しいペアの個数: " << sum_pair(start_1, start_2, k);
}

実行結果

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

合計がkに等しいペアの個数: 4

まとめ

本記事では、2つの連結リストを二重ループで総当たり的に走査することで、合計が指定値kに等しいペアの個数を求める方法を解説しました。シンプルで理解しやすい手法ですが、リストが長くなると計算量が増大します。効率化したい場合は、片方のリストの要素をunordered_setに格納しておき、もう片方の各要素に対して「k − 要素」が存在するかをO(1)で判定する方法があり、この場合はO(n + m)まで計算量を抑えられます。

  1. ソート済み双方向連結リストで積が指定値xと等しくなるトリプルの個数を数えるC++プログラム

    問題の概要 整数値を格納したソート済みの双方向連結リスト(doubly linked list)が与えられます。この課題の目標は、3つのノードのデータの積が指定された値xと等しくなるようなトリプル(三つ組)の個数を求めることです。 例えば、入力リンクリストが「3→4→1→2」でxが6の場合、積が6になるトリプルは(3, 1, 2)の1つだけなので、カウントは1となります。 入力例と出力例 例1 入力: linked list: [ 200→4→16→5→10→10→2 ]、x = 200 出力: 積が指定値xと等しくなるトリプルの個数: 3 説明: 該当するトリプルは以下の3つです。 (4

  2. C++で2つのBSTから合計が指定値xと等しいペアを数える方法

    2つの二分探索木(BST)と整数値 x が与えられます。この記事の目的は、BST_1 から1つのノード、BST_2 からもう1つのノードを選んだペアのうち、両ノードの値の合計が x に一致するものの個数を求めることです。具体的には、BST_1 のノードと BST_2 のノードのデータ部分を加算し、その合計が x と等しければカウントを1つ増やしていきます。具体例で確認してみましょう。入力出力 − 合計が指定値 x に等しい2つのBSTからのペアの数 − 1説明 − 該当するペアは (8, 6) です。入力出力 − 合計が指定値 x に等しい2つのBSTからのペアの数 − 2説明 − 該当するペ