0

I'm trying to understand why my solution to this problem is only partially working.

Problem:

Given a sorted array nums, remove the duplicates in-place such that each element appears only once and returns the new length.

Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.

My Solution:

var removeDuplicates = function(nums) {
    
    if (nums.length === 0) return 0;
    for (let i = 1; i <= nums.length; i++){
        if(nums[i] === nums[i-1]){
            nums.splice(nums[i], 1);
        }
    }
    return nums.length;
};

This is the outcome I'm getting on leetcode but I don't understand why my solution stops working and the '3s' are not removed?

Output screenshot:

image of the screenshot

1
  • 3
    You iterate forward and remove items. Each time you remove, everything after that item moves back a slot. So, if you get an array like [15, 19, 19, 19, 21] you'd find index 1 and 2 are the same, remove one, then the new item in index 2 is 19 from the old index 3. However, you just increase the counter i and never check it, moving over to check the (new) index 2 and 3. Commented Oct 12, 2020 at 20:40

5 Answers 5

3

When you splice an array while iterating over it, the whole array will change in-place. For example, let's say that indexes 0 and 1 are duplicates (i is 1). Then, if you remove index 1 from the array, what used to be at index 2 will now be at index 1, and what used to be at index 3 will now be at index 2, etc.

So, you need to subtract 1 from i when an element is removed, otherwise the next element will be skipped.

You also have an off-by-one-error - iterate i from 1 to i < nums.length so you don't go past the end of the array.

You also need to pass the index to remove to splice, not the value to remove.

var removeDuplicates = function(nums) {
    for (let i = 1; i < nums.length; i++){
        if(nums[i] === nums[i-1]){
            nums.splice(i, 1);
            i--;
        }
    }
    return nums.length;
};
console.log(removeDuplicates([0, 0, 0]));

Sign up to request clarification or add additional context in comments.

1 Comment

The alternative is to iterate backwards from nums.length - 1 to 0. Then you don't have to worry about maintaining the index, the shifts in elements don't affect the following iterations.
0

Simple version. Using functions already created

let array = new Set(nums);
let values = array.values();
return Array.from(values);

2 Comments

This uses O(n) extra memory, which is forbidden
Didn't know that
0

This'd also pass just fine on constant memory:

const removeDuplicates = function (nums) {
    
    let count = 0;
    
    nums.forEach(function (num) {
        if (num !== nums[count]) {
            nums[++count] = num;
        }
    });
    
    return nums.length && count + 1;
};

1 Comment

your solution doesn't remove the duplicate elements in the original array
0
function removeDuplicates(nums) {
  let i = 0;
  while(i < nums.length - 1) {
    i += 1 - ((nums[i] === nums[i+1]) && nums.splice(i, 1).length)
  }
  return nums.length;
}

Comments

0

C# simple solution:

public int RemoveDuplicates(int[] nums) {
        if (nums.Length == 0)
                return 0;
        var i = 0;
            var start = 0;
            var end = 0;

            while (end < nums.Length)
            {
                if (nums[start] != nums[end])
                {
                    nums[++i] = nums[end];
                    start = end;
                }
                end++;
            }

            return i + 1;
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.