LeetCode – Remove Duplicates from Sorted Array II (Java)

Follow up for “Remove Duplicates“: What if duplicates are allowed at most twice?

For example, given sorted array A = [1,1,1,2,2,3], your function should return length = 5, and A is now [1,1,2,2,3].

So this problem also requires in-place array manipulation.

Java Solution 1

We can not change the given array’s size, so we only change the first k elements of the array which has duplicates removed.

public int removeDuplicates(int[] nums) {
    if(nums==null){
        return 0;
    }
    if(nums.length<3){
        return nums.length;
    }
 
    int i=0;
    int j=1;
/*
 
         i, j    1 1 1 2 2 3
step1    0  1      i j
step2    1  2      i   j
step3    1  3        i   j
step4    2  4          i   j
 
*/
    while(j<nums.length){
        if(nums[j]==nums[i]){
            if(i==0){
                i++;
                j++;
            }else if(nums[i]==nums[i-1]){
                j++;
            }else{    
                i++;
                nums[i]=nums[j];
                j++;
            }
        }else{
            i++;
            nums[i]=nums[j];
            j++;
        }
    }
 
    return i+1;
}

The problem with this solution is that there are 4 cases to handle. If we shift our two points to right by 1 element, the solution can be simplified as the Solution 2.

Java Solution 2

public int removeDuplicates(int[] nums) {
    if(nums==null){
        return 0;
    }
 
    if (nums.length <= 2){
        return nums.length;
    }
/*
1,1,1,2,2,3
  i j
*/
    int i = 1; // point to previous
    int j = 2; // point to current
 
    while (j < nums.length) {
        if (nums[j] == nums[i] && nums[j] == nums[i - 1]) {
            j++;
        } else {
            i++;
            nums[i] = nums[j];
            j++;
        }
    }
 
    return i + 1;
}

15 thoughts on “LeetCode – Remove Duplicates from Sorted Array II (Java)”

  1. I think it’s easier to understand with a for loop and the notion of `last`.

    int removeDuplicates(int[] nums)
    {
    if (nums == null || nums.length == 0) return 0;

    if (nums.length <= 2) return nums.length;

    int last = 1;

    for (int i = 2 ; i < nums.length ; ++i)
    {
    if ((nums[last] < nums[i]) ||
    (nums[last-1] != nums[last]))
    {
    last++;
    nums[last] = nums[i];
    }
    }

    return last + 1;
    }


  2. class Solution {
    public:
    int removeDuplicates(vector& nums) {
    int lastIndex = 0, REP = 2, lastCnt = 1;
    for(int i = 1; i < nums.size(); i++) {
    if(nums[i] == nums[lastIndex] && lastCnt == REP) continue;
    lastCnt = (nums[lastIndex] == nums[i]) * lastCnt + 1;
    nums[++lastIndex] = nums[i];
    }
    return nums.size() == 0 ? 0 : lastIndex + 1;
    }
    };

  3. My approach is more similar to second. As long as the next element is duplicate you increment the second pointer, if not you can consistently copy value from second pointer to first and move both. Same solution works for version 1 of this problem, where you look at next 1 element, here next 2 elements.

    int n = nums.length;
    int i = 0;
    int j = 0;
    while (j < n) {
    while (j + 2 < n && nums[j+2] == nums[j]) {
    j++;
    }

    nums[i] = nums[j];
    j++;
    i++;

    }

    return i;

  4. public int removeDuplicates(int[] nums) {
    int dup_status = 1;
    int index = 1;
    for(int i = 0; i < nums.length-1; i++){
    if(nums[i] != nums[i+1] ){
    dup_status = 1;
    nums[index ++] = nums[i+1];
    }
    else if(nums[i] == nums[i+1] && dup_status < 2){
    dup_status ++;
    nums[index ++] = nums[i+1];
    }

    }
    return index;

    }

  5. similar to the duplicates I solution

    private static int[] removeDuplicateII(int[] a) {
    if (a.length < 3)
    return a;

    int i = 0;
    int j = 1;
    int k = 2;

    while (k < a.length) {
    if (a[i] == a[j] && a[j] == a[k]) {
    j++;
    k++;
    } else {
    i++;
    a[i] = a[j];
    j++;
    a[j] = a[k];
    k++;
    }
    }

    int[] b = Arrays.copyOf(a, i + 2);
    return b;
    }

  6. public static int remove_duplicates(int[] nums){

    int duplicates =0;

    for(int i = 0; i < nums.length; i++){

    if(i < nums.length-1 && nums[i] == nums[i+1]){

    int step = i++;

    while((i < nums.length-1 )&&nums[step] == nums[i++]){

    duplicates++;

    }

    }

    }

    return nums.length - duplicates;

    }

  7. How about this? A slight modification on the remove duplicates I

    int[] removeDuplicatesN(int[] arr, int N){

    int i=0,j=1, l=0;

    int n= arr.length;

    while(j<n){

    if(arr[i]==arr[j]){

    j++;

    l++;

    if(l<N) i++;

    }

    else{

    l=0;

    i++;

    arr[i] = arr[j];

    j++;

    }

    }

    return Arrays.copyOf(arr, i+1);

    }

  8. class Solution {
    public:
    int removeDuplicates(int A[], int n) {
    int currentPosition = 2;
    for (int i = 2; i < n; ++ i)
    if (A[i] != A[i-2])
    A[currentPosition++] = A[i];
    return min(currentPosition, n);
    }
    };

  9. The better solution is actually confusing. We can make the rule like this:
    Assign previous pointer to 1st element(a[0]) and current pointer to 2nd element(a[1]).
    1) if a[prev] != a[curr], {prev++; a[prev]=a[cur]; cur++;}
    2) else, {cur++;}

    you can remove the A[curr] == A[prev – 1] in this case.

  10. In the first solution, the loop starts from the second element. If input array has only one element it will cause index out of bounds error.

Leave a Comment