「这是我参与11月更文挑战的第23天,活动详情查看:2021最后一次更文挑战」
27.RemoveElement
题目
Given an integer array nums and an integer val, remove all occurrences of val in nums in-place. The relative order of the elements may be changed.
Since it is impossible to change the length of the array in some languages, you must instead have the result be placed in the first part of the array nums. More formally, if there are k elements after removing the duplicates, then the first k elements of nums should hold the final result. It does not matter what you leave beyond the first k elements.
Return k after placing the final result in the first k slots of nums.
Do not allocate extra space for another array. You must do this by modifying the input array in-place with O(1) extra memory.
Custom Judge:
The judge will test your solution with the following code:
int[] nums = [...]; // Input array
int val = ...; // Value to remove
int[] expectedNums = [...]; // The expected answer with correct length.
// It is sorted with no values equaling val.
int k = removeElement(nums, val); // Calls your implementation
assert k == expectedNums.length;
sort(nums, 0, k); // Sort the first k elements of nums
for (int i = 0; i < actualLength; i++) {
assert nums[i] == expectedNums[i];
}
If all assertions pass, then your solution will be accepted.
Example 1:
Input: nums = [3,2,2,3], val = 3
Output: 2, nums = [2,2,_,_]
Explanation: Your function should return k = 2, with the first two elements of nums being 2.
It does not matter what you leave beyond the returned k (hence they are underscores).
Example 2:
Input: nums = [0,1,2,2,3,0,4,2], val = 2
Output: 5, nums = [0,1,4,0,3,_,_,_]
Explanation: Your function should return k = 5, with the first five elements of nums containing 0, 0, 1, 3, and 4.
Note that the five elements can be returned in any order.
It does not matter what you leave beyond the returned k (hence they are underscores).
Constraints:
0 <= nums.length <= 1000 <= nums[i] <= 500 <= val <= 100
题目大意
给定一个数组nums和一个数val,不使用额外空间,去除nums中值为val的元素
因为nums.length >= 有效数组.length,所以只要将去除val后的有效数组(为了便于描述,下面都称去除val后的新数组为有效数组)放到nums的前部即可,并且元素顺序可以不按照原顺序
解题思路
双指针:定义left指向有效数组最后一位的后一位,right指针遍历数组
当right指向不为val的元素(有效元素)时,nums[left] = nums[right],即将有效元素放入有效数组,同时left后移一位,right继续遍历,直到right遍历完数组
代码
/**
* @param {number[]} nums
* @param {number} val
* @return {number}
*/
var removeElement = function (nums, val) {
let left = 0;
for (let right = 0; right < nums.length; ) {
if (nums[right] !== val) {
nums[left++] = nums[right];
}
right++;
}
return left;
};
复杂度
时间:O(n),最坏情况双指针遍历完数组
空间:O(1)
优化
假如nums = [1, 2, 3, 4],val = 1
此时right每次指向非val的元素时,都要赋值给他前面那个位置
考虑到有效数组的顺序可变,只要将4放到1的位置即可
因此,我们让right从数组尾部开始向前遍历,直到left > right
优化代码
/**
* @param {number[]} nums
* @param {number} val
* @return {number}
*/
var removeElement = function (nums, val) {
let left = 0;
let right = nums.length - 1;
while (left <= right) {
if (nums[left] === val) {
nums[left] = nums[right--];
} else {
left++;
}
}
return left;
};
复杂度
时间:O(n),最坏情况left遍历完数组
空间:O(1)