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

C++で2つの双方向リンクリストに共通するノード数を求める方法

問題の概要

2つの双方向リンクリスト(二重リンクリスト)が与えられたとき、両方のリストに共通して含まれるノードの総数を求めます。例えば、1つ目のリストが [15, 16, 10, 9, 7, 17]、2つ目のリストが [15, 16, 40, 6, 9] である場合、「15」「16」「9」の3つのノードが共通しているため、答えは3となります。

アルゴリズム

この問題は、ネストした2重ループを使って両方のリストを先頭から末尾まで走査することで解決できます。具体的な手順は以下の通りです。

  • 外側のループで、1つ目のリストの各ノードを順番に取り出します。
  • 内側のループで、そのノードの値が2つ目のリスト内のいずれかのノードと一致するかどうかを確認します。
  • 一致するノードが見つかった場合はカウンターを1増やし、内側のループを抜けます。
  • すべてのノードの照合が完了したら、カウンターの値を結果として返します。

実装例(C++)

#include<iostream>
using namespace std;
class Node {
   public:
      int data;
   Node *back, *front;
};
void append(Node** start, int new_data) {
   Node* new_node = new Node;
   new_node->data = new_data;
   new_node->back = NULL;
   new_node->front = (*start);
   if ((*start) != NULL)
      (*start)->back = new_node;
   (*start) = new_node;
}
int countCommonNodes(Node** start1, Node** start2) {
   Node* ptr = *start1;
   Node* ptr1 = *start2;
   int count = 0;
   while (ptr != NULL) {
      while (ptr1 != NULL) {
         if (ptr->data == ptr1->data) {
            count++;
            break;
         }
         ptr1 = ptr1->front;
      }
      ptr1 = *start2;
      ptr = ptr->front;
   }
   return count;
}
int main() {
   Node* first = NULL;
   Node* second = NULL;
   append(&first, 15);
   append(&first, 16);
   append(&first, 10);
   append(&first, 9);
   append(&first, 7);
   append(&first, 17);
   append(&second, 15);
   append(&second, 16);
   append(&second, 40);
   append(&second, 6);
   append(&second, 9);
   cout << "Number of common nodes:" << countCommonNodes(&first, &second);
}

出力

Number of common nodes:3

計算量と補足

上記の手法では、リスト1の各ノードに対してリスト2全体を走査するため、時間計算量は O(n × m)(n・m はそれぞれのリストの長さ)となります。リストの要素数が大きくなると処理が遅くなる点に注意してください。

パフォーマンスを向上させたい場合は、片方のリストの値をあらかじめハッシュセット(std::unordered_set)に格納しておき、もう片方のリストを1回だけ走査して存在チェックを行う方法が有効です。この場合、平均的な時間計算量は O(n + m) まで改善できます。

  1. C++で循環リンクリストのノード数をカウントする方法

    ノードから構成される循環リンクリスト(Circular Linked List)が与えられ、そのリスト内に存在するノードの総数を求めるのが課題です。 循環リンクリストとは、連結リストの一種であり、最初の要素が最後の要素を指し、最後の要素が最初の要素を指すという特徴を持つデータ構造です。片方向リンクリスト(Singly Linked List)でも双方向リンクリスト(Doubly Linked List)でも、この循環リンクリストとして実装することが可能です。 以下のプログラムでは、片方向リンクリストを循環リンクリストとして実装し、その中に含まれるノード数をカウントする方法を紹介します。 具体

  2. C++で二分木の2つのノード間の距離を求める方法

    問題の概要いくつかのノードを持つ二分木が与えられているとします。このとき、2つのノード u と v の間の「距離」、つまり一方のノードからもう一方のノードへ移動する際に通る辺(エッジ)の本数を求めることを考えます。例として、次のような二分木を扱います。 1 / \ 2 3 / \ / \ 4 5 6 7 \ 8この木において、ノード (4, 6) 間の距離は 4(経路:4 → 2 → 1 → 3 → 6)、ノード (5, 8) 間の