27. 移除元素
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O ( 1 ) O(1) O(1) 额外空间并原地修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。
示例 2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。
你不需要考虑数组中超出新长度后面的元素。
思考
方法一:
采用暴力法也不是无脑暴力法
- 设置变量valcount表示:目前在数组结尾的val值的个数
- 第一层for循环
- 第一层开始条件 i = 0
- 第一层结束条件 i < nums.length - valcount ,不用去查看结尾是val的数了
- 当 nums[ i ] ==val时,第二层for循环
- 第二层开始条件 j = nums.length - count - 1 , 因为已知结尾有valcount个val,所以从 nums.length - count - 1开始寻找数组最末尾并且值不是val的数以便进行交换
- 如果当前 j 指向的数等于valcount,valcount++, 并且此时j-1 == i时,从j = nums.length - count - 1到 i这些数都等于val ,所以此时返回 nums.length-valcount-1(这个1是i指向的val)
- 如果找到一个数不等于valcount,交换并break;
- 第二层结束条件 j>i
- 第二层开始条件 j = nums.length - count - 1 , 因为已知结尾有valcount个val,所以从 nums.length - count - 1开始寻找数组最末尾并且值不是val的数以便进行交换
- 第二层循环结束代表已经找到结尾一个不为val的数值并且成功交换,所以数组最末尾val的个数+1
方法二:
双指针法:left ,right
这里0 - left中无val值,遍历数组即可
实现
方法一:
package 力扣;
public class leetcode27 {
public static void main(String[] args) {
int[] nums={0,1,2,2,3,0,4,2};
int i = removeElement(nums, 2);
System.out.println(i);
}
public static int removeElement(int[] nums, int val) {
// 这里定义为 数组末尾已知的连续的val个数
int valcount=0;
// i < nums.length-valcount ,肯定不用查看后面的无用信息了
for (int i = 0; i < nums.length-valcount; i++) {
if(nums[i]==val){
int count=valcount;
// j从已知末尾val的前一个数开始,向前寻找一个值不等于val的数进行交换
for (int j=nums.length-1-count;j>i;j-- ){
// 如果末尾的值还是val
if(nums[j]==val) {
valcount++;
// 如果此时已经到i前一个数还没找到值不等于val的数 这里-1的1代表i指向的val
if((j-1)==i) return nums.length-valcount-1;
}
// 找到值等于val的数
if(nums[j]!=val){
nums[i]=nums[j];
nums[j]=val;
break;
}
}
// 成功交换 末尾val数加一
valcount++;
}
}
return nums.length-valcount;
}
}
方法二:
class Solution {
public int removeElement(int[] nums, int val) {
int n = nums.length;
int left = 0;
for (int right = 0; right < n; right++) {
if (nums[right] != val) {
nums[left] = nums[right];
left++;
}
}
return left;
}
}