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

C++で連結リストの中央から先頭に向かってk番目のノードを検索する方法

問題概要

この問題では、連結リスト(Linked List)と数値kが与えられます。求めるのは、連結リストの中央ノードから先頭(Head)に向かってk番目にあるノードです。

具体例を使って問題を確認してみましょう。

入力: 連結リスト: 4 → 2 → 7 → 1 → 9 → 12 → 8 → 10 → 5、k = 2

出力: 7

解説:

まず、中央ノードの値は 9 です。

そして、中央から先頭に向かって2番目のノードは 7 になります。

解法のアプローチ

連結リストの中央から先頭に向かってk番目の要素を見つけるには、まずリストを先頭から末尾まで一度走査し、ノードの総数nを求めます。

すると、中央から先頭に向かってk番目の要素は、先頭から数えて(n / 2 + 1 − k)番目の要素に相当することが分かります。

アルゴリズムの手順

1. リストを走査してノード総数nを取得します。
2. 中央の位置は n / 2 + 1 として計算できます(ノード数が偶数・奇数のどちらの場合でも機能します)。
3. 目的のノードの位置は (n / 2 + 1 − k) 番目です。
4. 計算結果が0以下になる場合(kが範囲外の場合)は -1 を返します。
5. 先頭から目的の位置まで再度走査し、該当ノードの値を返します。

このアルゴリズムの計算量は、リストを最大2回走査するため O(n) となり、追加のメモリ領域は不要で空間計算量は O(1) です。

ソリューションの実装例

#include <iostream>
using namespace std;

struct Node {
    int data;
    struct Node* next;
};

void pushNode(struct Node** head_ref, int new_data)
{
    struct Node* new_node = new Node;
    new_node->data = new_data;
    new_node->next = (*head_ref);
    (*head_ref) = new_node;
}

int findKmiddleNode(struct Node* head_ref, int k) {

    int n = 0;
    struct Node* counter = head_ref;
    while (counter != NULL) {
        n++;
        counter = counter->next;
    }
    int reqNode = ((n / 2 + 1) - k);

    if (reqNode <= 0)
        return -1;

    struct Node* current = head_ref;
    int count = 1;
    while (current != NULL) {
        if (count == reqNode)
            return (current->data);
        count++;
        current = current->next;
    }
}

int main()
{
    struct Node* head = NULL;
    int k = 2;
    pushNode(&head, 5);
    pushNode(&head, 10);
    pushNode(&head, 8);
    pushNode(&head, 12);
    pushNode(&head, 9);
    pushNode(&head, 1);
    pushNode(&head, 7);
    pushNode(&head, 2);
    pushNode(&head, 4);

    cout<<k<<"番目の要素(中央から先頭へ): "<<findKmiddleNode(head, k);

    return 0;
}

出力結果

2番目の要素(中央から先頭へ): 7

コードの解説

上記のプログラムでは、pushNode関数が新しいノードをリストの先頭に挿入していきます。findKmiddleNode関数は、まず最初のwhileループでリスト全体を走査してノード数nをカウントし、次に (n / 2 + 1 − k) で目的の位置reqNodeを算出します。reqNodeが0以下の場合は有効なノードが存在しないため -1 を返し、そうでなければ2回目の走査で該当位置のノードの値を返します。

  1. C++でリンクリスト内の最初の非重複要素を見つけるプログラム

    この問題では、サイズNのリンクリストLLが与えられます。求められているのは、リンクリスト内で最初に一度だけ出現する要素(非重複要素)を見つけるプログラムを作成することです。リンクリストとは、データ構造同士をポインタ(リンク)で順番につなげた一連のデータ構造です。問題の例具体例を使って問題を確認してみましょう。入力:LL = 4 => 6 => 2 => 4 => 1 => 2 => 6 => 5出力:1解説:このリンクリストでは、一度だけ出現する要素は「1」と「5」です。そのうち、リンクリストの先頭に近い方に出現しているのは「1」なので、答えは1となり

  2. C++でマルチレベル連結リストをフラット化する方法を解説

    この記事では、マルチレベル連結リスト(Multilevel Linked List)をフラット化するプログラムをC++で作成する方法について解説します。フラット化とは、第1レベルのノードをすべて先に並べ、その後に第2レベルのノードが続くように、階層構造を持つリストを1本の直線的な連結リストへ変換する操作のことです。マルチレベル連結リストとはマルチレベル連結リストとは、多次元的なデータ構造の一種です。各ノードは2つのポインタを持ちます。1つは次のノードを指す「next」ポインタ、もう1つは1つ以上のノードからなる子リストを指す「child」ポインタです。この子ポインタは、他のリストのノードを指す