it-swarm.com.ru

Как эффективно удалить дубликаты из массива без использования Set

Меня попросили написать собственную реализацию для удаления дублированных значений в массиве. Вот что я создал. Но после испытаний с 1 000 000 элементов потребовалось очень много времени, чтобы закончить. Есть ли что-то, что я могу сделать, чтобы улучшить свой алгоритм или какие-либо ошибки, чтобы удалить? 

Мне нужно написать свою собственную реализацию - не использовать использовать Set , HashSet и т.д. Или любые другие инструменты, такие как итераторы. Просто массив для удаления дубликатов.

public static int[] removeDuplicates(int[] arr) {

    int end = arr.length;

    for (int i = 0; i < end; i++) {
        for (int j = i + 1; j < end; j++) {
            if (arr[i] == arr[j]) {                  
                int shiftLeft = j;
                for (int k = j+1; k < end; k++, shiftLeft++) {
                    arr[shiftLeft] = arr[k];
                }
                end--;
                j--;
            }
        }
    }

    int[] whitelist = new int[end];
    for(int i = 0; i < end; i++){
        whitelist[i] = arr[i];
    }
    return whitelist;
}
35
ashur

Поскольку этот вопрос по-прежнему привлекает большое внимание, я решил ответить на него, скопировав этот ответ из Code Review.SE :

Вы придерживаетесь той же философии, что и пузырьковая сортировка. очень, очень, очень медленно. Вы пробовали это?

  • Сортируйте ваш неупорядоченный массив с помощью quicksort . Быстрая сортировка намного быстрее. чем сортировка по пузырькам (я знаю, вы не сортируете, но алгоритм, который вы используете , почти такой же, как и сортировка по пузырькам для обхода массива). 

  • Затем начните удалять дубликаты (повторяющиеся значения будут рядом с каждым Другим). В цикле for вы можете иметь два индекса: source и destination. (В каждом цикле вы копируете source в destination, если они не совпадают , И увеличиваете оба на 1). Каждый раз, когда вы найдете дублируйте ваш источник приращения (и не выполняйте копирование) . @morgano

2
ashur

вы можете воспользоваться помощью Set Collection

int end = arr.length;
Set<Integer> set = new HashSet<Integer>();

for(int i = 0; i < end; i++){
  set.add(arr[i]);
}

теперь, если вы будете перебирать этот set , он будет содержать только уникальные значения. Итерация кода выглядит так:

Iterator it = set.iterator();
while(it.hasNext()) {
  System.out.println(it.next());
}
35
Android Killer

Примечание: я предполагаю, что массив отсортирован.

Код:

int[] input = new int[]{1, 1, 3, 7, 7, 8, 9, 9, 9, 10};
int current = input[0];
boolean found = false;

for (int i = 0; i < input.length; i++) {
    if (current == input[i] && !found) {
        found = true;
    } else if (current != input[i]) {
        System.out.print(" " + current);
        current = input[i];
        found = false;
    }
}
System.out.print(" " + current);

Результат:

  1 3 7 8 9 10
14
Kick Buttowski

Поскольку вы можете предположить, что диапазон составляет от 0 до 1000, есть очень простое и эффективное решение.

//Throws an exception if values are not in the range of 0-1000
public static int[] removeDuplicates(int[] arr) {
    boolean[] set = new boolean[1001]; //values must default to false
    int totalItems = 0;

    for (int i = 0; i < arr.length; ++i) {
        if (!set[arr[i]]) {
            set[arr[i]] = true;
            totalItems++;
        }
    }

    int[] ret = new int[totalItems];
    int c = 0;
    for (int i = 0; i < set.length; ++i) {
        if (set[i]) {
            ret[c++] = i;
        }
    }
    return ret;
}

Это выполняется за линейное время O (n). Предостережение: возвращаемый массив сортируется, поэтому, если это недопустимо, этот ответ недопустим.

7
Esailija

Небольшое изменение самого исходного кода, удалив самый внутренний цикл for.

public static int[] removeDuplicates(int[] arr){
    int end = arr.length;

    for (int i = 0; i < end; i++) {
        for (int j = i + 1; j < end; j++) {
            if (arr[i] == arr[j]) {                  
                /*int shiftLeft = j;
                for (int k = j+1; k < end; k++, shiftLeft++) {
                    arr[shiftLeft] = arr[k];
                }*/
                arr[j] = arr[end-1];
                end--;
                j--;
            }
        }
    }

    int[] whitelist = new int[end];
    /*for(int i = 0; i < end; i++){
        whitelist[i] = arr[i];
    }*/
    System.arraycopy(arr, 0, whitelist, 0, end);
    return whitelist;
}
6
Pavan Kumar
class Demo 
{
    public static void main(String[] args) 
    {
        int a[]={3,2,1,4,2,1};
        System.out.print("Before Sorting:");
        for (int i=0;i<a.length; i++ )
        {
            System.out.print(a[i]+"\t");
        }
        System.out.print ("\nAfter Sorting:");
        //sorting the elements
        for(int i=0;i<a.length;i++)
        {
            for(int j=i;j<a.length;j++)
            {
                if(a[i]>a[j])
                {
                    int temp=a[i];
                    a[i]=a[j];
                    a[j]=temp;
                }

            }
        }

        //After sorting
        for(int i=0;i<a.length;i++)
        {
            System.out.print(a[i]+"\t");
        }
        System.out.print("\nAfter removing duplicates:");
        int b=0;
        a[b]=a[0];
        for(int i=0;i<a.length;i++)
        {
            if (a[b]!=a[i])
            {
                b++;
                a[b]=a[i];
            }
        }
        for (int i=0;i<=b;i++ )
        {
            System.out.print(a[i]+"\t");
        }
    }
}
  OUTPUT:Before Sortng:3 2 1 4 2 1 After Sorting:1 1 2 2 3 4 
                Removing Duplicates:1 2 3 4
6
user3752541

Существует много решений этой проблемы. 

  1. Сортировочный подход 

    • Вы сортируете свой массив и разрешаете только уникальные элементы 
  2. Сетевой подход 

    • Вы объявляете HashSet, куда вы помещаете все элементы, тогда у вас есть только уникальные. 
  3. Вы создаете логический массив, который представляет элементы, все готово возвращенные (это зависит от ваших данных в массиве). 

Если вы имеете дело с большим количеством данных, я бы выбрал 1. решение. Так как вы не выделяете дополнительную память и сортировка происходит довольно быстро. Для небольшого набора данных сложность будет n ^ 2, но для большого я будет n log n.

5
Damian Leszczyński - Vash

Что делать, если вы создадите два логических массива: 1 для отрицательных значений и 1 для положительных значений и начнете все это в false.

Затем вы циклически перебираете входной массив и просматриваете массивы, если уже приняли значение .. Если нет, вы добавляете его в выходной массив и помечаете его как уже использованное.

4
DaMachk

Это простой способ сортировки элементов в массиве.

public class DublicatesRemove {
    public static void main(String args[]) throws Exception {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        System.out.println("enter size of the array");
        int l = Integer.parseInt(br.readLine());
        int[] a = new int[l];
        // insert elements in the array logic
        for (int i = 0; i < l; i++) 
        {
            System.out.println("enter a element");
            int el = Integer.parseInt(br.readLine());
            a[i] = el;
        }
        // sorting elements in the array logic
        for (int i = 0; i < l; i++) 
        {
            for (int j = 0; j < l - 1; j++) 
            {
                if (a[j] > a[j + 1])
                {
                    int temp = a[j];
                    a[j] = a[j + 1];
                    a[j + 1] = temp;
                }
            }
        }
        // remove duplicate elements logic
        int b = 0;
        a[b] = a[0];
        for (int i = 1; i < l; i++)
        {
            if (a[b] != a[i])
            {
                b++;
                a[b]=a[i];

            }

        }
        for(int i=0;i<=b;i++)
        {
            System.out.println(a[i]);
        }


    }
}
2
Tummala srikanth
package com.pari.practice;

import Java.util.HashSet;
import Java.util.Iterator;

import com.pari.sort.Sort;

public class RemoveDuplicates {

 /**
 * brute force- o(N square)
 * 
 * @param input
 * @return
 */
public static int[] removeDups(int[] input){
    boolean[] isSame = new boolean[input.length];
    int sameNums = 0;

    for( int i = 0; i < input.length; i++ ){
        for( int j = i+1; j < input.length; j++){
            if( input[j] == input[i] ){ //compare same
                isSame[j] = true;
                sameNums++;
            }
        }
    }

    //compact the array into the result.
    int[] result = new int[input.length-sameNums];
    int count = 0;
    for( int i = 0; i < input.length; i++ ){
        if( isSame[i] == true) {
            continue;
        }
        else{
            result[count] = input[i];
            count++;
        }
    }

    return result;
}

/**
 * set - o(N)
 * does not guarantee order of elements returned - set property
 * 
 * @param input
 * @return
 */
public static int[] removeDups1(int[] input){
    HashSet myset = new HashSet();

    for( int i = 0; i < input.length; i++ ){
        myset.add(input[i]);
    }

    //compact the array into the result.
    int[] result = new int[myset.size()];
    Iterator setitr = myset.iterator();
    int count = 0;
    while( setitr.hasNext() ){
        result[count] = (int) setitr.next();
        count++;
    }

return result;
}

/**
 * quicksort - o(Nlogn)
 * 
 * @param input
 * @return
 */
public static int[] removeDups2(int[] input){
    Sort st = new Sort();
    st.quickSort(input, 0, input.length-1); //input is sorted

    //compact the array into the result.
    int[] intermediateResult = new int[input.length];
    int count = 0;
    int prev = Integer.MIN_VALUE;
    for( int i = 0; i < input.length; i++ ){
        if( input[i] != prev ){
            intermediateResult[count] = input[i];
            count++;
        }
        prev = input[i];
    }

    int[] result = new int[count];
    System.arraycopy(intermediateResult, 0, result, 0, count);

    return result;
}


public static void printArray(int[] input){
    for( int i = 0; i < input.length; i++ ){
        System.out.print(input[i] + " ");
    }
}

public static void main(String[] args){
    int[] input = {5,6,8,0,1,2,5,9,11,0};
    RemoveDuplicates.printArray(RemoveDuplicates.removeDups(input));
    System.out.println();
    RemoveDuplicates.printArray(RemoveDuplicates.removeDups1(input));
    System.out.println();
    RemoveDuplicates.printArray(RemoveDuplicates.removeDups2(input));
}
}

Результат: 5 6 8 0 1 2 9 11 

0 1 2 5 6 8 9 11 

0 1 2 5 6 8 9 11 

Я только что написал приведенный выше код для тестирования. Благодарю.

2
user3222017
int tempvar=0; //Variable for the final array without any duplicates
     int whilecount=0;    //variable for while loop
     while(whilecount<(nsprtable*2)-1) //nsprtable can be any number
     {
//to check whether the next value is idential in case of sorted array       
if(temparray[whilecount]!=temparray[whilecount+1])
        {
            finalarray[tempvar]=temparray[whilecount];
            tempvar++;
            whilecount=whilecount+1;
        }
        else if (temparray[whilecount]==temparray[whilecount+1])
        {
            finalarray[tempvar]=temparray[whilecount];
            tempvar++;
            whilecount=whilecount+2;
        }
     }

Надеюсь, что это помогает или решает цель.

1
driftking9987
public static int[] removeDuplicates(int[] arr){
    HashSet<Integer> set = new HashSet<>();
    final int len = arr.length;
    //changed end to len
    for(int i = 0; i < len; i++){
        set.add(arr[i]);
    }

    int[] whitelist = new int[set.size()];
    int i = 0;
    for (Iterator<Integer> it = set.iterator(); it.hasNext();) {
        whitelist[i++] = it.next();
    }
    return whitelist;
}

Запускается в O(N) время вместо вашего O (N ^ 3) времени

1
David Xu
public static void main(String args[]) {
    int[] intarray = {1,2,3,4,5,1,2,3,4,5,1,2,3,4,5};

    Set<Integer> set = new HashSet<Integer>();
    for(int i : intarray) {
        set.add(i);
    }

    Iterator<Integer> setitr = set.iterator();
    for(int pos=0; pos < intarray.length; pos ++) {
        if(pos < set.size()) {
            intarray[pos] =setitr.next();
        } else {
            intarray[pos]= 0;
        }
    }

    for(int i: intarray)
    System.out.println(i);
}
1
Programmer

Вам нужно отсортировать массив, затем зациклить и удалить дубликаты. Поскольку вы не можете использовать другие инструменты, вам нужно писать код самостоятельно.

Вы можете легко найти примеры быстрой сортировки в Java в Интернете (на котором основан этот пример).

public static void main(String[] args) throws Exception {
    final int[] original = new int[]{1, 1, 2, 8, 9, 8, 4, 7, 4, 9, 1};
    System.out.println(Arrays.toString(original));
    quicksort(original);
    System.out.println(Arrays.toString(original));
    final int[] unqiue = new int[original.length];
    int prev = original[0];
    unqiue[0] = prev;
    int count = 1;
    for (int i = 1; i < original.length; ++i) {
        if (original[i] != prev) {
            unqiue[count++] = original[i];
        }
        prev = original[i];
    }
    System.out.println(Arrays.toString(unqiue));
    final int[] compressed = new int[count];
    System.arraycopy(unqiue, 0, compressed, 0, count);
    System.out.println(Arrays.toString(compressed));
}

private static void quicksort(final int[] values) {
    if (values.length == 0) {
        return;
    }
    quicksort(values, 0, values.length - 1);
}

private static void quicksort(final int[] values, final int low, final int high) {
    int i = low, j = high;
    int pivot = values[low + (high - low) / 2];
    while (i <= j) {
        while (values[i] < pivot) {
            i++;
        }
        while (values[j] > pivot) {
            j--;
        }
        if (i <= j) {
            swap(values, i, j);
            i++;
            j--;
        }
    }
    if (low < j) {
        quicksort(values, low, j);
    }
    if (i < high) {
        quicksort(values, i, high);
    }
}

private static void swap(final int[] values, final int i, final int j) {
    final int temp = values[i];
    values[i] = values[j];
    values[j] = temp;
}

Итак, процесс проходит в 3 этапа.

  1. Сортировать массив - O(nlgn)
  2. Удалить дубликаты - O(n)
  3. Сжать массив - O(n)

Так что это значительно улучшает ваш подход O(n^3).

Результат:

[1, 1, 2, 8, 9, 8, 4, 7, 4, 9, 1]
[1, 1, 1, 2, 4, 4, 7, 8, 8, 9, 9]
[1, 2, 4, 7, 8, 9, 0, 0, 0, 0, 0]
[1, 2, 4, 7, 8, 9]

ПРАВКА

OP заявляет значения внутри массива на самом деле не имеют значения. Но я могу предположить, что диапазон составляет от 0 до 1000. Это классический случай, когда можно использовать сортировку O(n).

Мы создаем массив размером range +1, в данном случае 1001. Затем мы перебираем данные и увеличиваем значения в каждом индексе, соответствующем точке данных.

Затем мы можем сжать результирующий массив, отбрасывая значения, которые не были увеличены. Это делает значения уникальными, так как мы игнорируем количество.

public static void main(String[] args) throws Exception {
    final int[] original = new int[]{1, 1, 2, 8, 9, 8, 4, 7, 4, 9, 1, 1000, 1000};
    System.out.println(Arrays.toString(original));
    final int[] buckets = new int[1001];
    for (final int i : original) {
        buckets[i]++;
    }
    final int[] unique = new int[original.length];
    int count = 0;
    for (int i = 0; i < buckets.length; ++i) {
        if (buckets[i] > 0) {
            unique[count++] = i;
        }
    }
    final int[] compressed = new int[count];
    System.arraycopy(unique, 0, compressed, 0, count);
    System.out.println(Arrays.toString(compressed));
}

Результат:

[1, 1, 2, 8, 9, 8, 4, 7, 4, 9, 1, 1000, 1000]
[1, 2, 4, 7, 8, 9, 1000]
1
Boris the Spider

Для отсортированного массива просто проверьте следующий индекс:

//sorted data!
public static int[] distinct(int[] arr) {
    int[] temp = new int[arr.length];

    int count = 0;
    for (int i = 0; i < arr.length; i++) {
        int current = arr[i];

        if(count > 0 )
            if(temp[count - 1] == current)
                continue;

        temp[count] = current;
        count++;
    }

    int[] whitelist = new int[count];
    System.arraycopy(temp, 0, whitelist, 0, count);

    return whitelist;
}
1
mc_fish

Не очень интересно обновлять пользовательский ввод, однако учитывая ваши ограничения ...

public int[] removeDup(int[] nums) {
  Arrays.sort(nums);
  int x = 0;
  for (int i = 0; i < nums.length; i++) {
    if (i == 0 || nums[i] != nums[i - 1]) {
    nums[x++] = nums[i];
    }
  }
  return Arrays.copyOf(nums, x);
}

Сортировка массива может быть легко заменена любым алгоритмом nlog (n).

1
Maurizio Cucchiara

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

    public static int[] removeDuplicates(int[] numbers) {
    Entry[] entries = new Entry[numbers.length];
    int size = 0;
    for (int i = 0 ; i < numbers.length ; i++) {
        int nextVal = numbers[i];
        int index = nextVal % entries.length;
        Entry e = entries[index];
        if (e == null) {
            entries[index] = new Entry(nextVal);
            size++;
        } else {
            if(e.insert(nextVal)) {
                size++;
            }
        }
    }
    int[] result = new int[size];
    int index = 0;
    for (int i = 0 ; i < entries.length ; i++) {
        Entry current = entries[i];
        while (current != null) {
            result[i++] = current.value;
            current = current.next;
        }
    }
    return result;
}

public static class Entry {
    int value;
    Entry next;

    Entry(int value) {
        this.value = value;
    }

    public boolean insert(int newVal) {
        Entry current = this;
        Entry prev = null;
        while (current != null) {
            if (current.value == newVal) {
                return false;
            } else if(current.next != null) {
                prev = current;
                current = next;
            }
        }
        prev.next = new Entry(value);
        return true;
    }
}
1
Eagle

Как насчет этого, только для отсортированного массива из чисел, для печати массива без дубликатов, без использования Set или других коллекций, просто Array: 

 public static int[] removeDuplicates(int[] array) {
    int[] nums =new int[array.length];
    int addedNum = 0;
    int j=0;
    for(int i=0;i<array.length;i++) {
        if (addedNum != array[i]) {
        nums[j] = array[i];
        j++;
        addedNum = nums[j-1];
        }
    }
    return Arrays.copyOf(nums, j);
}

Массив из 1040 дублированных чисел, обработанных за 33020 наносекунд ( 0,033020 миллисекунд ). 

0
pandabear
 package javaa;

public class UniqueElementinAnArray 
{

 public static void main(String[] args) 
 {
    int[] a = {10,10,10,10,10,100};
    int[] output = new int[a.length];
    int count = 0;
    int num = 0;

    //Iterate over an array
    for(int i=0; i<a.length; i++)
    {
        num=a[i];
        boolean flag = check(output,num);
        if(flag==false)
        {
            output[count]=num;
            ++count;
        }

    }

    //print the all the elements from an array except zero's (0)
    for (int i : output) 
    {
        if(i!=0 )
            System.out.print(i+"  ");
    }

}

/***
 * If a next number from an array is already exists in unique array then return true else false
 * @param arr   Unique number array. Initially this array is an empty.
 * @param num   Number to be search in unique array. Whether it is duplicate or unique.
 * @return  true: If a number is already exists in an array else false 
 */
public static boolean check(int[] arr, int num)
{
    boolean flag = false;
    for(int i=0;i<arr.length; i++)
    {
        if(arr[i]==num)
        {
            flag = true;
            break;
        }
    }
    return flag;
}

}

0
Avinash Pande

Почему все люди не проверяют это ниже строк?

Мне нужно написать собственную реализацию - не использовать Set, HashSet и т.д. Или любые другие инструменты, такие как итераторы. Просто массив для удаления дубликатов. 

Я публикую очень простую реализацию с заботой о вышеприведенной строке.

public class RemoveDuplicates {

public static void main(String[] args) {

    int[] arr = { 1, 2, 3, 4, 2, 3, 1 }; // input array
    int len = arr.length;
    for (int i = 0; i < arr.length; i++) {
        for (int j = i + 1; j < len; j++) {
            if (arr[i] == arr[j]) {
                while (j < (len) - 1) {
                    arr[j] = arr[j - 1];
                    j++;
                }
                len--;
            }
        }
    }
    for (int i = 0; i < len; i++) {
        System.out.print("  " +arr[i]);
    }

   }
 }

Ввод: 1, 2, 3, 4, 2, 3, 1

Результат: 1 2 3 4

0
Ved Prakash
public static void main(String[] args) {
        Integer[] intArray = { 1, 1, 1, 2, 4, 2, 3, 5, 3, 6, 7, 3, 4, 5 };
        Integer[] finalArray = removeDuplicates(intArray);
        System.err.println(Arrays.asList(finalArray));
    }

    private static Integer[] removeDuplicates(Integer[] intArray) {
        int count = 0;
        Integer[] interimArray = new Integer[intArray.length];
        for (int i = 0; i < intArray.length; i++) {
            boolean exists = false;
            for (int j = 0; j < interimArray.length; j++) {
                if (interimArray[j]!=null && interimArray[j] == intArray[i]) {
                    exists = true;
                }
            }
            if (!exists) {
                interimArray[count] = intArray[i];
                count++;
            }
        }
        final Integer[] finalArray = new Integer[count];
        System.arraycopy(interimArray, 0, finalArray, 0, count);
        return finalArray;
    }
0
venkata harish
public void removeDup(){ 
String[] arr = {"1","1","2","3","3"};
          boolean exists = false;
          String[] arr2 = new String[arr.length];
          int count1 = 0;
          for(int loop=0;loop<arr.length;loop++)
            {
              String val = arr[loop];
              exists = false;
              for(int loop2=0;loop2<arr2.length;loop2++)
              {     
                  if(arr2[loop2]==null)break;
                  if(arr2[loop2]==val){
                        exists = true;
                }
              }
              if(!exists) {
                    arr2[count1] = val;
                    count1++;
              }
            }
}
0
Pradeep
public static int[] removeDuplicates(int[] arr) {

int end = arr.length;

 HashSet<Integer> set = new HashSet<Integer>(end);
    for(int i = 0 ; i < end ; i++){
        set.add(arr[i]);
    }
return set.toArray();
}
0
Falguni

Я чувствую, что идея Android Killer великолепна, но мне просто интересно, сможем ли мы использовать HashMap. Поэтому я провел небольшой эксперимент. И я обнаружил, что HashMap кажется быстрее, чем HashSet.

Вот код:

    int[] input = new int[1000000];

    for (int i = 0; i < input.length; i++) {
        Random random = new Random();
        input[i] = random.nextInt(200000);
    }

    long startTime1 = new Date().getTime();
    System.out.println("Set start time:" + startTime1);

    Set<Integer> resultSet = new HashSet<Integer>();

    for (int i = 0; i < input.length; i++) {
        resultSet.add(input[i]);
    }

    long endTime1 = new Date().getTime();
    System.out.println("Set end time:"+ endTime1);
    System.out.println("result of set:" + (endTime1 - startTime1));     
    System.out.println("number of Set:" + resultSet.size() + "\n");

    long startTime2 = new Date().getTime();
    System.out.println("Map start time:" + startTime1);

    Map<Integer, Integer> resultMap = new HashMap<Integer, Integer>();

    for (int i = 0; i < input.length; i++) {
        if (!resultMap.containsKey(input[i]))
            resultMap.put(input[i], input[i]);
    }

    long endTime2 = new Date().getTime();
    System.out.println("Map end Time:" + endTime2);
    System.out.println("result of Map:" + (endTime2 - startTime2));
    System.out.println("number of Map:" + resultMap.size());

Вот результат:

Set start time:1441960583837
Set end time:1441960583917
result of set:80
number of Set:198652

Map start time:1441960583837
Map end Time:1441960583983
result of Map:66
number of Map:198652
0
jonathan

Вот мое решение. Сложность времени o (n ^ 2)

public String removeDuplicates(char[] arr) {
        StringBuilder sb = new StringBuilder();

        if (arr == null)
            return null;
        int len = arr.length;

        if (arr.length < 2)
            return sb.append(arr[0]).toString();

        for (int i = 0; i < len; i++) {

            for (int j = i + 1; j < len; j++) {
                if (arr[i] == arr[j]) {
                    arr[j] = 0;

                }
            }
            if (arr[i] != 0)
                sb.append(arr[i]);
        }

        return sb.toString().trim();
    }
0
Türkmen Mustafa Demirci

Если вам разрешено использовать потоки Java 8:

Arrays.stream(arr).distinct().toArray();
0
Tomin

Итак, вы не можете использовать Set или другие коллекции. Одно решение, которого я пока не вижу, основано на использовании фильтра Блума , который по сути является массивом битов, так что, возможно, он отвечает вашим требованиям.

Фильтр Блума - это приятная и очень удобная техника, быстрая и компактная, которая может быть использована для быстрой проверки существования элемента в наборе без сохранения самого набора или элементов. Он имеет (как правило, небольшой) уровень ложных срабатываний, но не имеет ложных отрицательных показателей Другими словами, на ваш вопрос, если фильтр Блума сообщает вам, что элемент еще не был просмотрен, вы можете быть уверены, что его не было. Но если он говорит, что элемент был замечен, вам действительно нужно проверить. Это по-прежнему экономит много времени, если в вашем списке не слишком много дубликатов (для них не нужно делать циклы, за исключением маловероятного ложного срабатывания - вы обычно выбираете этот показатель на основе того, сколько пространство, которое вы готовы выделить для фильтра Блума (практическое правило: менее 10 бит на уникальный элемент при частоте ложных срабатываний 1%).

Существует множество реализаций фильтров Блума, см., Например, здесь или здесь , поэтому я не буду повторять это в этом ответе. Давайте просто предположим, что API, описанный в этой последней ссылке, в частности, description of put(E e):

true если биты фильтра Блума изменились в результате этой операции. Если биты изменились, это определенно первый раз, когда объект был добавлен в фильтр. Если биты не изменились, это может быть первым объектом, который был добавлен в фильтр. (...)

Реализация, использующая такой фильтр Блума, будет:

public static int[] removeDuplicates(int[] arr) {
    ArrayList<Integer> out = new ArrayList<>();
    int n = arr.length;
    BloomFilter<Integer> bf = new BloomFilter<>(...);  // decide how many bits and how many hash functions to use (compromise between space and false positive rate)

    for (int e : arr) {
        boolean might_contain = !bf.put(e);
        boolean found = false;
        if (might_contain) {
            // check if false positive
            for (int u : out) {
                if (u == e) {
                    found = true;
                    break;
                }
            }
        }
        if (!found) {
            out.add(e);
        }
    }
    return out.stream().mapToInt(i -> i).toArray();
}

Очевидно, что если вы можете изменить входящий массив на месте, тогда нет необходимости в ArrayList: в конце, когда вы знаете фактическое количество уникальных элементов, просто arraycopy() из них.

0
Pierre D

Это не использует Set, Map, List или любую дополнительную коллекцию, только два массива:

package arrays.duplicates;

import Java.lang.reflect.Array;
import Java.util.Arrays;

public class ArrayDuplicatesRemover<T> {

    public static <T> T[] removeDuplicates(T[] input, Class<T> clazz) {
        T[] output = (T[]) Array.newInstance(clazz, 0);
        for (T t : input) {
            if (!inArray(t, output)) {
                output = Arrays.copyOf(output, output.length + 1);
                output[output.length - 1] = t;
            }
        }
        return output;
    }

    private static <T> boolean inArray(T search, T[] array) {
        for (T element : array) {
            if (element.equals(search)) {
                return true;
            }
        }
        return false;
    }

}

И главное проверить это

package arrays.duplicates;

import Java.util.Arrays;

public class TestArrayDuplicates {

    public static void main(String[] args) {
        Integer[] array = {1, 1, 2, 2, 3, 3, 3, 3, 4};
        testArrayDuplicatesRemover(array);
    }

    private static void testArrayDuplicatesRemover(Integer[] array) {
        final Integer[] expectedResult = {1, 2, 3, 4};
        Integer[] arrayWithoutDuplicates = ArrayDuplicatesRemover.removeDuplicates(array, Integer.class);
        System.out.println("Array without duplicates is supposed to be: " + Arrays.toString(expectedResult));
        System.out.println("Array without duplicates currently is: " + Arrays.toString(arrayWithoutDuplicates));
        System.out.println("Is test passed ok?: " + (Arrays.equals(arrayWithoutDuplicates, expectedResult) ? "YES" : "NO"));
    }

}

И вывод:

Array without duplicates is supposed to be: [1, 2, 3, 4]
Array without duplicates currently is: [1, 2, 3, 4]
Is test passed ok?: YES
0
Juan Furattini

Вот более простой и лучший способ сделать это, используя вместо этого arraylists:

public static final <T> ArrayList<T> removeDuplicates(ArrayList<T> in){
    ArrayList<T> out = new ArrayList<T>();
    for(T t : in) 
        if(!out.contains(t)) 
            out.add(t);
    return out;
}
0
Jeremiah

Это вопрос интервью: удаляйте дубликаты из массива. Я не должен использовать какие-либо наборы или коллекции. Полное решение:

public class Test4 {
public static void main(String[] args) {
     int a[] = {1, 2, 2, 3, 3, 3, 6,6,6,6,6,66,7,65}; 
              int newlength =    lengthofarraywithoutduplicates(a);
              for(int i = 0 ; i < newlength ;i++) {
                  System.out.println(a[i]);
              }//for
}//main

private static int lengthofarraywithoutduplicates(int[] a) {
     int count = 1 ;
     for (int i = 1; i < a.length; i++) {
          int ch = a[i];
          if(ch != a[i-1]) {
              a[count++] = ch;
          }//if
    }//for
    return count;

}//fix

}//end1
0
Soudipta Dutta