I noticed a particular timing behaviour while solving LeetCode problem 27. Remove Element:
Given an integer array
numsand an integerval, remove all occurrences ofvalinnumsin-place. The order of the elements may be changed. Then return the number of elements innumswhich are not equal toval.Consider the number of elements in
numswhich are not equal tovalbek, to get accepted, you need to do the following things:
- Change the array
numssuch that the firstkelements ofnumscontain the elements which are not equal toval. The remaining elements ofnumsare not important as well as the size ofnums.- Return
k.
When I submitted the code below, I got a time-out:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int count=0;
for(int i=0;i<nums.size();i++){
if(nums[i]==val){
for(int j=i;j+1<nums.size();j++){
nums[j]=nums[j+1];
count+=1;
}
i--;
}
}
return nums.size()-count;
}
};
Then I tried to use a variable to record the value of nums.size() and use it as the loop condition. This time the code finished within the alotted time.
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int count=0,size=nums.size();
for(int i=0;i<size;i++){
if(nums[i]==val){
for(int j=i;j+1<size;j++){
nums[j]=nums[j+1];
count+=1;
}
i--;
size--;
}
}
return size;
}
};
I don't understand why this could be such an important difference.
I would like to know the time that .size() uses and its internal code, with its time complexity.
Calling
nums.size()on each iteration or storing it in a variable first does not actually make much of a difference. The real issue is that you run into an infinite loop when the last element is the value to remove, as you keep attempting to shift the remaining elements (of which there are none) down over and over. In the second version of your code, you decrement the size when shifting, which precludes going into the section of thevectorthat contains useless elements not part of the solution.On another note, since the question states that the size of
numsafter the method executes doesn't matter, you can directly delete the matching elements from the vector. This can be easily done in one line withstd::erase(which has linear time complexity).