C++でソート済み連結リストIIから重複要素を削除する方法
ソート済みの連結リストが与えられたとき、2回以上出現した要素をすべて取り除き、1度だけ現れる要素(ユニークな要素)だけを残すことを考えます。
例えば、リストが [1,1,1,2,2,3,5,6,6,7,8] の場合、出力は [3,5,7,8] となります。これは、1・2・6 がそれぞれ複数回出現している一方で、3・5・7・8 は1度しか現れていないためです。
アルゴリズムの手順
この問題は、ダミーノード(番兵ノード)を活用することで効率的に解くことができます。手順は以下の通りです。
- 値 -1 を持つダミーノードを作成し、
prev := NULL、dummyPtr := dummyと初期化します。 headが NULL でない限り、以下を繰り返します。- 次ノードが存在しない、または現在の値と次ノードの値が異なる場合(ユニークな要素の場合):
dummyPtr->nextにheadを接続します。tempにhead->nextを保存し、head->nextを NULL にして切り離します。head := tempとして処理を進め、dummyPtrを1つ進めます。
- 重複が見つかった場合:
prev := head、head := head->nextとします。headが NULL でなく、かつheadの値がprevの値と等しい間、両方のポインタを進め続け、重複ブロック全体をスキップします。
- 次ノードが存在しない、または現在の値と次ノードの値が異なる場合(ユニークな要素の場合):
- 最後に、ダミーノードの
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(-1);
ListNode* prev = NULL;
ListNode* dummyPtr = dummy;
ListNode* nextNode;
while(head){
if(!head->next || head->val != head->next->val){
dummyPtr->next = head;
ListNode* temp = head->next;
head->next = NULL;
head = temp;
dummyPtr = dummyPtr->next;
} else {
prev = head;
head = head->next;
while(head && head->val == prev->val){
prev = head;
head = head->next;
}
}
}
return dummy->next;
}
};
main(){
Solution ob;
vector<int> v = {1,1,1,2,2,3,5,6,6,7,8};
ListNode *head = make_list(v);
print_list(ob.deleteDuplicates(head));
}入力
[1,1,1,2,2,3,5,6,6,7,8]
出力
[3, 5, 7, 8]
このアルゴリズムの計算量は、リストを一度走査するだけでよいため O(n) となり、追加の領域もポインタ数個分のみで済むため、非常に効率的な手法といえます。
-
【Android】ソート済みリンクリストから重複を削除する方法をわかりやすく解説
はじめに この記事では、Androidアプリ開発において、ソート済みのリンクリスト(LinkedList)から重複する要素を削除する方法を解説します。Java標準ライブラリのLinkedHashSetを活用すれば、要素の順序を保ったまま重複だけを簡単に除去できます。 実装手順 ステップ1:新規プロジェクトの作成 まず、Android Studioで新しいプロジェクトを作成します。メニューから「File」⇒「New Project」を選択し、必要な項目を入力してプロジェクトを生成してください。 ステップ2:レイアウトファイル(activity_main.xml)の編集 次に、res/layout
-
C++でソート・回転済み連結リストの回転数を求める方法
問題概要ある連結リストが与えられます。このリストは、最初に昇順にソートされ、その後 K 個のノード分だけ回転(ローテーション)されたものです。この記事の目的は、元のリストに対する回転数 K を求めることです。たとえば、以下のような連結リストが入力として与えられたとします。5 → 7 → 9 → 1 → 3このリストは、元のソート済みリスト1 → 3 → 5 → 7 → 9を 2 ノード分だけ回転したものになっています。つまり、この場合の K は 2 です。具体例で理解する例 1入力: リスト: 5 → 7 → 9 → 1 → 3出力:連結リストの要素: 5 7 9 1 3ソート・回転済み連結リ