Временная сложность удаления дубликатов в arraylist со компаратором [duplicate]

Симон Моурир дал этот пример :

object o = null;
DateTime d = (DateTime)o;  // NullReferenceException

, где unboxing преобразование (литье) из object (или из одного из классов System.ValueType или System.Enum или из типа интерфейса) - тип значения (кроме Nullable<>) сам по себе дает NullReferenceException.

В другом направлении конверсия бокса из a Nullable<>, которая имеет HasValue, равную false , на ссылочный тип, может дать ссылку null, которая затем может привести к NullReferenceException. Классический пример:

DateTime? d = null;
var s = d.ToString();  // OK, no exception (no boxing), returns ""
var t = d.GetType();   // Bang! d is boxed, NullReferenceException

Иногда бокс происходит по-другому. Например, с помощью этого не общего метода расширения:

public static void MyExtension(this object x)
{
  x.ToString();
}

следующий код будет проблематичным:

DateTime? d = null;
d.MyExtension();  // Leads to boxing, NullReferenceException occurs inside the body of the called method, not here.

Эти случаи возникают из-за специальных правил, используемых во время выполнения при боксе Nullable<> экземпляров.

28
задан cletus 28 July 2010 в 13:43
поделиться

13 ответов

Проверять каждый элемент на каждый другой элемент

Наивное решение - проверять каждый элемент на каждый другой элемент. Это расточительно и дает решение O (n2), даже если вы только переходите вперед.

Сортировка, а затем удаление дубликатов

Лучшее решение сортирует массив, а затем проверяет каждый элемент рядом с ним, чтобы найти дубликаты. Выберите эффективную сортировку, и это O (n log n).

Недостаток решения на основе сортировки не поддерживается. Однако дополнительный шаг может позаботиться об этом. Поместите все записи (в уникальном отсортированном массиве) в хеш-таблицу, которая имеет доступ O (1). Затем перебираем исходный массив. Для каждого элемента проверьте, находится ли он в хеш-таблице. Если это так, добавьте его в результат и удалите из хеш-таблицы. Вы получите результирующий массив, который имеет порядок оригинала, причем каждый элемент находится в том же положении, что и его первое вхождение.

Линейные сортировки целых чисел

Если вы имея дело с целыми числами некоторого фиксированного диапазона, вы можете сделать еще лучше, используя сортировку radix. Если вы предполагаете, что все номера находятся в диапазоне от 0 до 1 000 000, например, вы можете выделить бит-вектор около 1000,001. Для каждого элемента в исходном массиве вы устанавливаете соответствующий бит на основе его значения (например, значение 13 приводит к установке 14-го бита). Затем перейдите к исходному массиву, проверьте, находится ли он в битовом векторе. Если это так, добавьте его в массив результатов и очистите этот бит от битового вектора. Это O (n) и пространство трейдинга для времени.

Решение хэш-таблицы

Это приводит нас к лучшему решению всего: сортировка на самом деле является отвлечением, хотя и полезным. Создайте хэш-таблицу с доступом O (1). Перейдите к исходному списку. Если он уже не в хэш-таблице, добавьте его в массив результатов и добавьте его в хеш-таблицу. Если он находится в хеш-таблице, игнорируйте его.

Это, безусловно, лучшее решение. Так почему же остальные? Потому что такие проблемы связаны с адаптацией знаний, которые у вас есть (или должны иметь) к проблемам, и их уточнения на основе предположений, которые вы принимаете в решении. Разработка решения и понимание мышления, стоящего за ним, гораздо полезнее, чем срывание решения.

Кроме того, хеш-таблицы не всегда доступны. Возьмите встроенную систему или что-то там, где пространство ОЧЕНЬ ограничено. Вы можете реализовать быструю сортировку в нескольких кодах операций, гораздо меньше, чем любая хеш-таблица.

71
ответ дан cletus 23 August 2018 в 23:59
поделиться
  • 1
    В этом вопросе результирующий массив сохраняет порядок входного массива. – pascal 28 July 2010 в 08:17
  • 2
    Полное и ясное резюме – Jingguo Yao 5 December 2013 в 14:21
  • 3
    Следует четко указать, что хеш-таблицы дают вам ожидаемое постоянное время, а не гарантированное постоянное время. – rbrito 22 February 2015 в 15:31
  • 4
    Хотя хеш-таблица не позволяет добавлять повторяющиеся элементы, если вы добавляете все числа в хэш-таблицу, а затем просто печатаете ее, вы можете достичь того же результата. какова точка выше, чтобы использовать некоторые условия if и сделать логику более сложной? – Gökhan Akduğan 21 February 2016 в 03:20
  • 5
    @ GökhanAkduğan Наиболее очевидные причины, которые были упомянуты: значимость заказа, отсутствие доступности хэш-таблицы, сильные ограничения пространства. – Szymon Brych 22 September 2017 в 06:23

Обработать номера как ключи.

for each elem in array:
if hash(elem) == 1 //duplicate
  ignore it
  next
else
  hash(elem) = 1
  add this to resulting array 
end
Если вы знаете о таких данных, как диапазон чисел, и если он конечен, вы можете инициализировать этот большой массив с помощью ZERO. [f 2]

1
ответ дан bhups 23 August 2018 в 23:59
поделиться

Вы можете использовать синтаксис «in» и «not in» в python, который делает его довольно простым.

Сложность выше, чем метод хеширования, хотя, поскольку «не в» эквивалентно линейному обходу, чтобы выяснить, существует ли эта запись или нет.

li = map(int, raw_input().split(","))
a = []
for i in li:
    if i not in a:
        a.append(i)
print a
0
ответ дан Deepak Pathania 23 August 2018 в 23:59
поделиться
    indexOutput = 1;
    outputArray[0] = arrayInt[0];
    int j;
    for (int i = 1; i < arrayInt.length; i++) {            
        j = 0;
        while ((outputArray[j] != arrayInt[i]) && j < indexOutput) {
            j++;
        }
        if(j == indexOutput){
           outputArray[indexOutput] = arrayInt[i];
           indexOutput++;
        }         
    }
1
ответ дан dhayyati 23 August 2018 в 23:59
поделиться

Мое решение (O(N)) не использует дополнительную память, но массив должен быть отсортирован (мой класс использует алгоритм сортировки вставки, но это не имеет значения.):

  public class MyArray
        {
            //data arr
            private int[] _arr;
            //field length of my arr
            private int _leght;
            //counter of duplicate
            private int countOfDup = 0;
            //property length of my arr
            public int Length
            {
                get
                {
                    return _leght;
                }
            }

            //constructor
            public MyArray(int n)
            {
                _arr = new int[n];
                _leght = 0;
            }

            // put element into array
            public void Insert(int value)
            {
                _arr[_leght] = value;
                _leght++;
            }

            //Display array
            public void Display()
            {
                for (int i = 0; i < _leght; i++) Console.Out.Write(_arr[i] + " ");
            }

            //Insertion sort for sorting array
            public void InsertSort()
            {
                int t, j;
                for (int i = 1; i < _leght; i++)
                {
                    t = _arr[i];
                    for (j = i; j > 0; )
                    {
                        if (_arr[j - 1] >= t)
                        {
                            _arr[j] = _arr[j - 1];
                            j--;
                        }
                        else break;
                    }
                    _arr[j] = t;
                }
            }

            private void _markDuplicate()
            {
                //mark duplicate Int32.MinValue
                for (int i = 0; i < _leght - 1; i++)
                {
                    if (_arr[i] == _arr[i + 1])
                    {
                        countOfDup++;
                        _arr[i] = Int32.MinValue;
                    }
                }
            }

            //remove duplicates O(N) ~ O(2N) ~ O(N + N)
            public void RemoveDups()
            {
                _markDuplicate();
                if (countOfDup == 0) return; //no duplicate
                int temp = 0;

                for (int i = 0; i < _leght; i++)
                {
                    // if duplicate remember and continue
                    if (_arr[i] == Int32.MinValue) continue;
                    else //else need move 
                    {
                        if (temp != i) _arr[temp] = _arr[i];
                        temp++;
                    }
                }
                _leght -= countOfDup;
            }
        }

и Main

static void Main(string[] args)
{
     Random r = new Random(DateTime.Now.Millisecond);
     int i = 11;
     MyArray a = new MyArray(i);
     for (int j = 0; j < i; j++)
     {
        a.Insert(r.Next(i - 1));
     }

     a.Display();
     Console.Out.WriteLine();
     a.InsertSort();
     a.Display();
     Console.Out.WriteLine();
     a.RemoveDups();
     a.Display();

    Console.ReadKey();
}
0
ответ дан isxaker 23 August 2018 в 23:59
поделиться

Если вам не нужно сохранять исходный объект, вы можете его закодировать и создать новый массив уникальных значений. В C # используйте Список, чтобы получить доступ к требуемой функциональности. Это не самое привлекательное или интеллектуальное решение, но оно работает.

int[] numbers = new int[] {1,2,3,4,5,1,2,2,2,3,4,5,5,5,5,4,3,2,3,4,5};
List<int> unique = new List<int>();

foreach (int i in numbers)
     if (!unique.Contains(i))
          unique.Add(i);

unique.Sort();
numbers = unique.ToArray();
2
ответ дан Jonathon Reinhart 23 August 2018 в 23:59
поделиться

Я согласен с Cletus. Используйте QuickSort , затем удалите дубликаты

0
ответ дан Laramie 23 August 2018 в 23:59
поделиться

Это может быть сделано в амортизированном O (n) с использованием набора на основе хэш-таблицы.

Псевдоэкс:

s := new HashSet
c := 0
for each el in a
  Add el to s.
    If el was not already in s, move (copy) el c positions left.
    If it was in s, increment c. 
2
ответ дан Matthew Flaschen 23 August 2018 в 23:59
поделиться
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class testing {
    public static void main(String[] args) {
        EligibleOffer efg = new EligibleOffer();
        efg.setCode("1234");
        efg.setName("hey");
        EligibleOffer efg1 = new EligibleOffer();
        efg1.setCode("1234");
        efg1.setName("hey1");
        EligibleOffer efg2 = new EligibleOffer();
        efg2.setCode("1235");
        efg2.setName("hey");
        EligibleOffer efg3 = new EligibleOffer();
        efg3.setCode("1235");
        efg3.setName("hey");
        EligibleOffer[] eligibleOffer = { efg, efg1,efg2 ,efg3};
        removeDupliacte(eligibleOffer);
    }

    public static EligibleOffer[] removeDupliacte(EligibleOffer[] array) {
        List list = Arrays.asList(array);
        List list1 = new ArrayList();
        int len = list.size();
        for (int i = 0; i <= len-1; i++) {
            boolean isDupliacte = false;
            EligibleOffer eOfr = (EligibleOffer) list.get(i);
            String value = eOfr.getCode().concat(eOfr.getName());
            if (list1.isEmpty()) {
                list1.add(list.get(i));
                continue;
            }
            int len1 = list1.size();
            for (int j = 0; j <= len1-1; j++) {
                EligibleOffer eOfr1 = (EligibleOffer) list1.get(j);
                String value1 = eOfr1.getCode().concat(eOfr1.getName());
                if (value.equals(value1)) {
                    isDupliacte = true;
                    break;
                }
                System.out.println(value+"\t"+value1);
            }
            if (!isDupliacte) {
                list1.add(eOfr);
            }
        }
        System.out.println(list1);
        EligibleOffer[] eligibleOffer = new EligibleOffer[list1.size()];
        list1.toArray(eligibleOffer);
        return eligibleOffer;
    }
}
0
ответ дан Nivi 23 August 2018 в 23:59
поделиться
Time O(n) space O(n) 

#include <iostream>
    #include<limits.h>
    using namespace std;
    void fun(int arr[],int size){

        int count=0;
        int has[100]={0};
        for(int i=0;i<size;i++){
            if(!has[arr[i]]){
               arr[count++]=arr[i];
               has[arr[i]]=1;
            }
        }
     for(int i=0;i<count;i++)
       cout<<arr[i]<<" ";
    }

    int main()
    {
        //cout << "Hello World!" << endl;
        int arr[]={4, 8, 4, 1, 1, 2, 9};
        int size=sizeof(arr)/sizeof(arr[0]);
        fun(arr,size);

        return 0;
    }
0
ответ дан rjnitt 23 August 2018 в 23:59
поделиться

Это сегмент кода i, созданный на C ++, попробуйте его

#include <iostream>

using namespace std;

int main()
{
   cout << " Delete the duplicate" << endl; 

   int numberOfLoop = 10;
   int loopCount =0;
   int indexOfLargeNumber = 0;
   int largeValue = 0;
   int indexOutput = 1;

   //Array to hold the numbers
   int arrayInt[10] = {};
   int outputArray [10] = {};

   // Loop for reading the numbers from the user input
   while(loopCount < numberOfLoop){       
       cout << "Please enter one Integer number" << endl;
       cin  >> arrayInt[loopCount];
       loopCount = loopCount + 1;
   }



    outputArray[0] = arrayInt[0];
    int j;
    for (int i = 1; i < numberOfLoop; i++) {            
        j = 0;
        while ((outputArray[j] != arrayInt[i]) && j < indexOutput) {
            j++;
        }
        if(j == indexOutput){
           outputArray[indexOutput] = arrayInt[i];
           indexOutput++;
        }         
    }

   cout << "Printing the Non duplicate array"<< endl;

   //Reset the loop count
   loopCount =0;

   while(loopCount < numberOfLoop){ 
       if(outputArray[loopCount] != 0){
        cout <<  outputArray[loopCount] << endl;
    }     

       loopCount = loopCount + 1;
   }   
   return 0;
}
0
ответ дан Vanji 23 August 2018 в 23:59
поделиться
public class RemoveDuplicateArray {
    public static void main(String[] args) {
        int arr[] = new int[] { 1, 2, 3, 4, 5, 6, 7, 2, 3, 4, 9 };
        int size = arr.length;
        for (int i = 0; i < size; i++) {
            for (int j = i+1; j < size; j++) {
                if (arr[i] == arr[j]) {
                    while (j < (size) - 1) {
                        arr[j] = arr[j + 1];
                        j++;
                    }
                    size--;
                }
            }
        }
        for (int i = 0; i < size; i++) {
            System.out.print(arr[i] + "  ");
        }
    }

}

output - 1 2 3 4 5 6 7 9

0
ответ дан Ved Prakash 23 August 2018 в 23:59
поделиться

Используйте реализацию Set. HashSet , TreeSet или LinkedHashSet , если его Java.

0
ответ дан Zaki 23 August 2018 в 23:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: