简体   繁体   中英

Removing duplicates from sorted array list and return size in java without using extra space

Is there a better way to remove dups from the array list compared to the below code which does the work in O(n) when encountered with larger input. Any suggestions would be appreciated. Thank you.

Note :- Can't use any extra space and should be solved in place.

Input :- It will be a sorted array with dups.

Code :-

    public int removeDuplicates(ArrayList<Integer> a) {

        if(a.size()>1){
        for( int i=0;i<a.size()-1;i++ ) {

          if(a.get(i).intValue() == a.get(i+1).intValue() ) {
            a.remove(i);
            i--; 
          }

      }
      }
    return a.size();

    }

Please test the code here at coder pad link.

https://coderpad.io/MXNFGTJC

If this code is for removing elements of an unsorted list, then:

  1. The algorithm is incorrect.
  2. The Question is a duplicate of How do I remove repeated elements from ArrayList? (for example ...)

If the list is sorted , then:

  1. The algorithm is correct.
  2. The algorithm is NOT O(N) . It is actually O(ND) on average where N is the list length and D is the number of duplicates.

    Why? Because ArrayList::remove(int) is an on average O(N) operation!

There are two efficient ways to remove a large number of elements from a list:

  1. Create a new list, iterate the old list and add the elements that you want to retain to the new list. Then either discard the old list or clear it and copy the new list to the old one.

    This works efficiently (O(N)) for all standard kinds of list.

  2. Perform a sliding window removal. The algorithm with arrays is like this:

      int i = 0; for (int j = 0; j < array.length; j++) { if (should remove array[j]) { // do nothing } else { array[i++] = array[j]; } } // trim array to length i, or assign nulls or something. 

    As you can see, this performs one pass through the array, and is O(N) . It also avoids allocating any temporary space.

    You can implement the sliding window removal using ArrayList::get(int) and ArrayList::set(int, <E>) ... followed by repeated removal of the last element to trim the list.

Here are some ideas to improve performance:

  1. Removing elements one by one from an ArrayList can be expensive since you must shift the all contents after that element. Instead of ArrayList you might consider a different list implementation which allows O(1) removal. Alternatively, if you must use ArrayList and are not allowed any temporary data structures, you can rebuild the array by chaining together recursive calls that use set() instead of remove() .

  2. For lists with millions of elements, consider a parallel processing solution to leverage the power of multiple processes. Java streams are a simple way to achieve this.

List<Integer> l = new ArrayList<Integer>();
//add some elements to l
System.out.println(l.stream().distinct().collect(Collectors.toList()));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM