最近在重新学习一下数据结构与算法的知识点, 只有将知识运用起来才能更好地掌握知识, 所以在学习了有关数组的知识之后, 在 LeetCode 上选择 tag 为 Array 的相关题目来学习一下, 在这里记录一下.
本题为 easy 难度的 Remove Element : 题目意思很容易理解, 就是在不分配额外内存的情况下, 将数组中非选定的元素放到数组的前面, 返回数组中非选定元素的长度, 返回数组的顺序可以是随意的.
思路 1 : 很容易联想到在排序中, 前后两个指针, 交换数组位置的做法.
头指针指向第一个元素, 尾指针指向最后一个元素.
class Solution {
public int removeElement(int[] nums, int val) {
if(nums.length <= 0)
return 0;
if(nums.length == 1) {
if(val == nums[0])
return 0;
else
return 1;
}
int first = 0;
int last = nums.length - 1;
while(first < last) {
while(nums[last] == val && last > first)
last--;
while(nums[first] != val && first < last)
first++;
swap(nums, first, last);
first++;
last--;
}
return ++last;
}
public void swap(int[] nums, int p, int q) {
int temp = nums[p];
nums[p] = nums[q];
nums[q] = temp;
}
}
上面的代码是不能 AC 的. 分析一下错误, 首先, 交换数组两个元素之后, first ++ 和 last -- 是没有必要的, 在前面的两个 while 循环中可以处理该情况. 其次在三个 while 中都有 first < last 语句是冗余的, 在第一个 while 循环中可以用 if 来进行处理, 这样每走一步, 都进行了判断, 其实复杂度是差不多的.
class Solution {
public int removeElement(int[] nums, int val) {
if(nums == null || nums.length == 0) {
return 0;
}
int first = 0;
int last = nums.length - 1;
while(first <= last) {
if(nums[first] != val)
first++;
else if(nums[last] == val)
last--;
else {
int temp = nums[first];
nums[first] = nums[last];
nums[last] = temp;
}
}
return first;
}
}
一个比较大的疑惑在于 first <= last , 当 first 和 last 相等的时候应该就结束循环了, 为什么还要加上 = 号.
思路二 : 因为对数组的顺序没有要求, 所以可以只记录不是给定元素的数组元素.
class Solution {
public int removeElement(int[] nums, int val) {
int current = 0;
for(int i = 0; i < nums.length; i++) {
if(nums[i] != val) {
nums[current] = nums[i];
current ++;
}
}
return current;
}
}
相比而言, 前面的两个指针的方法在时间复杂度上没有什么提升, 所以推荐使用这个方法.