C++でソート済み配列から重複を削除する方法(各要素は最大2回まで許容)
ソートされた配列 nums が与えられたとき、同じ要素が最大2回まで現れるように、配列自体を書き換える形(インプレース)で重複を削除し、新しい長さを返すことを考えます。
この問題の重要な制約は、追加のメモリを使用できないという点です。つまり、O(1)の追加領域だけで解決しなければなりません。
例えば、入力配列が [0,0,0,1,1,1,1,2,3,3] の場合、出力は [0,0,1,1,2,3,3] となり、新しい長さは 7 になります。
アルゴリズムの考え方
この問題は「二ポインタ(書き込み位置と読み取り位置)」を使うテクニックで効率的に解けます。ポイントは、既に確定した末尾2つの要素と比較することで、「3連続以上の重複」を防ぐことです。
手順
- 書き込み位置
lenを 2 に初期化し、配列サイズをnとします。 n <= 2の場合は、どの要素も削除不要なのでそのままnを返します。i = 2からn - 1までループします。nums[i]がnums[len - 2]またはnums[len - 1]のいずれかと異なる場合(= まだ2連続になっていない場合)、nums[len] = nums[i]としてコピーし、lenを1増やします。
- 最後に
lenを返します。
この方法なら、各要素は時間計算量 O(n)、追加空間 O(1) で処理できます。
C++での実装例
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int len = 2;
int n = nums.size();
if(n <= 2)return n;
for(int i = 2; i < n; i++){
if( nums[i] != nums[len - 2] || nums[i] != nums[len - 1]){
nums[len] = nums[i];
len++;
}
}
return len;
}
};
main(){
Solution ob;
vector<int> v = {0,0,0,1,1,1,1,2,3,3};
cout << ob.removeDuplicates(v);
}入力
[0,0,0,1,1,1,1,2,3,3]
出力
7
まとめ
このアルゴリズムでは、配列の先頭2要素は必ず残るため len を 2 から開始し、3番目以降の要素について「直前に確定した2要素との比較」を行うことで、同一要素が3回以上連続して現れるのを防いでいます。条件式で OR(||)を使っているため、直前2つのうちどちらか一方でも異なればその要素を採用でき、正しく「最大2回まで」というルールを実現できます。
-
JavaでArrayListから重複要素を削除する方法を解説
本記事では、JavaのArrayList(配列リスト)から重複する要素を削除する方法について詳しく解説します。 リスト(List)とは、要素を順序付けて格納し、順番にアクセスできるコレクションのことです。インデックスベースのメソッドを使って、要素の挿入・更新・削除・検索を行うことができます。ただし、リストは重複した要素を持つことが許されているため、場合によっては重複を取り除く処理が必要になります。 処理内容のデモンストレーション 以下に、実際の動作例を示します。 入力: 定義されたリスト: [Java, Scala, Python, Java] 期待される出力: 重複削除後のリスト: [Jav
-
Pythonでソート済み配列から重複要素を削除する方法
ここでは、ソート済みのリストから重複する要素をすべて削除し、その後の配列の長さ(ユニークな要素の個数)を返す問題を扱います。重要な制約として、O(1)の追加メモリで実行する必要があります。つまり、新しい配列を作成せずに、元の配列をインプレース(in-place)で操作しなければなりません。問題の例例えば、次のような入力が与えられたとします。A = [1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 5, 5, 5, 6]この場合、重複を除いたユニークな要素は「1, 2, 3, 4, 5, 6」の6つなので、出力は 6 となります。解法のアプローチこの問題は、以下の手順で解くことができ