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

C++でソート済み連結リストから重複要素を削除する方法

ソート済みの連結リスト(リンクリスト)が与えられたとき、各要素が1回だけ出現するように、すべての重複を取り除くことを考えます。

たとえば、入力が [1,1,2,3,3,3,4,5,5] の場合、出力は [1,2,3,4,5] となります。リストがすでにソートされているため、同じ値を持つノードは必ず隣接しており、隣接するノード同士を比較するだけで重複を検出できるのがポイントです。

アルゴリズムの流れ

この問題は、ダミーノードを使ったシンプルな走査で解決できます。手順は以下の通りです。

  • 値が -inf(INT_MIN)の新しいノード「dummy」を作成します
  • dummy の next を head(元のリストの先頭)に設定します
  • curr = dummy として初期化します
  • curr が NULL でない限り、以下を繰り返します
    • next = curr の次のノードとします
    • next が NULL でなく、かつ next の値が curr の値と等しい間、next を次々と進めます
    • curr の next を next に接続し直します(重複ノードをスキップ)
    • curr = next として処理を進めます
  • 最後に dummy の next を返します

C++での実装例

それでは、実際の実装を見て理解を深めましょう。

#include <bits/stdc++.h>
using namespace std;
class ListNode{
    public:
        int val;
        ListNode *next;
        ListNode(int data){
            val = data;
            next = NULL;
        }
};
ListNode *make_list(vector<int> v){
    ListNode *head = new ListNode(v[0]);
    for(int i = 1; i<v.size(); i++){
        ListNode *ptr = head;
        while(ptr->next != NULL){
            ptr = ptr->next;
        }
        ptr->next = new ListNode(v[i]);
    }
    return head;
}
void print_list(ListNode *head){
    ListNode *ptr = head;
    cout << "[";
    while(ptr){
        cout << ptr->val << ", ";
        ptr = ptr->next;
    }
    cout << "]" << endl;
}
class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        ListNode*dummy = new ListNode(INT_MIN);
        dummy->next = head;
        ListNode * curr = dummy;
        while(curr){
            ListNode * next = curr->next;
            while(next && next->val==curr->val)
                next = next->next;
            curr->next = next;
            curr=next;
        }
        return dummy->next;
    }
};
main(){
    Solution ob;
    vector<int> v = {1,1,2,3,3,3,4,5,5};
    ListNode *head = make_list(v);
    print_list(ob.deleteDuplicates(head));
}

入力

{1,1,2,3,3,3,4,5,5}

出力

[1, 2, 3, 4, 5]

計算量について

このアルゴリズムは、リスト内の各ノードを一度だけ訪問するため、時間計算量は O(n) です。また、ダミーノード1つ分の追加メモリしか使用しないため、空間計算量は O(1) となり、非常に効率的な解法といえます。

  1. JavaScriptでリンクリストから要素を削除する方法

    リンクリストから要素を削除する基本の考え方 リンクリスト(連結リスト)から要素を削除する処理は非常にシンプルです。削除したいノードへの参照を失う(参照を切り離す)だけで実現できます。ただし、削除する位置によって処理が異なるため、次の3つのケースを考慮する必要があります。 ケース1:先頭(ヘッド)から削除する場合 先頭の要素を削除する場合は、head = head.next と代入するだけでOKです。これにより最初のノードへの参照が失われ、headは2番目のノードを指すようになります。 ケース2:末尾(テール)から削除する場合 末尾の要素を削除する場合は、最後から2番目のノードの node.ne

  2. 【Android】ソート済みリンクリストから重複を削除する方法をわかりやすく解説

    はじめに この記事では、Androidアプリ開発において、ソート済みのリンクリスト(LinkedList)から重複する要素を削除する方法を解説します。Java標準ライブラリのLinkedHashSetを活用すれば、要素の順序を保ったまま重複だけを簡単に除去できます。 実装手順 ステップ1:新規プロジェクトの作成 まず、Android Studioで新しいプロジェクトを作成します。メニューから「File」⇒「New Project」を選択し、必要な項目を入力してプロジェクトを生成してください。 ステップ2:レイアウトファイル(activity_main.xml)の編集 次に、res/layout