第四题:移除元素

题目

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
说明:
为什么返回数值是整数,但输出的答案是数组呢?
请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。

示例 1:
输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2]
解释:函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案。
示例 2:
输入:nums = [0,1,2,2,3,0,4,2], val = 2
输出:5, nums = [0,1,4,0,3]
解释:函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。

方法一:暴力破解法

算法思想:

利用两层for循环来实现对数组元素的移除。第一层for循环实现对数组nums的遍历操作;第二层for循环实现元素的移动操作。对于给定的值val,在第二层for循环之前,要进行if条件的判断,if(nums[i]==val)说明要执行第二层循环,把此时数组元素nums[i]的下一个元素赋值给nums[i],这在第二层for循环中这样实现:nums[j-1] = nums[j],此时j = I + 1,或者j = i,nums[j] = nums[j +1],是相等的。
不过在这个算法中,重要的是如果if条件成立,执行完第二层循环之后,i就要减一,数组长度也要减一。(因为数组中与给定值val相等的都被覆盖掉了,那为什么要I- -呢?这是因为:这样才能确保在移动元素后,下一轮循环会检查当前位置的元素进行if条件判断。)

算法步骤:

  1. 初始化一个变量 new_array_lenggth,并将其赋值为输入数组 nums 的长度,表示新数组的初始长度。
  2. 使用一个循环遍历数组 nums 中的每个元素,循环变量 i 从 0 到 new_array_lenggth-1
  3. 在循环中,检查当前元素 nums[i] 是否等于目标值 val
  4. 如果相等,则执行以下操作:使用一个内部循环,循环变量 ji+1new_array_lenggth-1,将后面的元素向前移动一个位置。将 nums[j] 的值赋给 nums[j-1],实现了向前移动元素的操作。将循环变量 i 减去 1,相当于将当前位置重复检查一次,以确保所有等于 val 的元素都被处理将 new_array_lenggth 减去 1,表示数组长度减少了一个元素。
  5. 重复步骤 2 和步骤 3,直到遍历完整个数组。
  6. 返回最终的数组长度 new_array_lenggth,表示新数组中不包含目标值 val 的元素的个数。

简而言之,这个算法通过双重循环来遍历并处理数组中的元素。当找到目标值时,通过向前移动元素和更新数组长度来移除目标值。最终返回的是新数组中不包含目标值的元素个数。

代码程序(C++):

int removeElement(vector<int>& nums, int val) {
    
    
	int new_array_lenggth = nums.size();

	for (int i = 0; i < new_array_lenggth; i++) {
    
    
		if (nums[i] == val) {
    
    
			for (int j = i + 1; j < new_array_lenggth; j++) {
    
    
				nums[j - 1] = nums[j];
			}
			i--;
			new_array_lenggth--;
		}
		
	}
	return new_array_lenggth;
}

代码程序(python):

算法测试:

在这里插入图片描述

在这里插入图片描述

方法二:双指针法

双指针法的算法思想是通过使用两个指针,一个快指针和一个慢指针,在遍历数组的过程中实现元素的移除操作。该方法适用于需要移除数组中指定值的元素的情况。

具体步骤如下:

1、初始化两个指针,一个指向数组的起始位置,称为慢指针,另一个指向数组的当前位置,称为快指针。
2、遍历数组,通过快指针移动来检查数组中的每个元素。
3、如果当前元素与目标值不相等,则将快指针指向的元素复制到慢指针指向的位置,并同时移动快指针和慢指针。
4、如果当前元素与目标值相等,则只移动快指针,跳过当前元素,不进行复制操作。
5、重复步骤 3 和步骤 4,直到遍历完整个数组。
6、返回慢指针的位置作为新数组的长度。
通过这种方法,可以实现在原地修改数组,将不等于目标值的元素移动到数组的前面,并返回新数组的长度。整个过程中,只遍历了一遍数组,因此时间复杂度为 O(n),其中 n 是数组的长度。

程序代码(C++):

int removeElement(vector<int>& nums, int val) {
    
    
    int left = 0; // 左指针
    int right = 0; // 右指针

    while (right < nums.size()) {
    
    
        if (nums[right] != val) {
    
    
            nums[left] = nums[right];
            left++;
        }
        right++;
    }

    return left;
}

程序代码(Python):

def removeElement(nums, val):
    left = 0
    right = 0

    while right < len(nums):
        if nums[right] != val:
            nums[left] = nums[right]
            left += 1
        right += 1

    return left

算法测试:

在这里插入图片描述
在这里插入图片描述

参考文献:

[1] https://programmercarl.com/0027.%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0.html#%E6%80%9D%E8%B7%AF

注:本文只用于学习和学术交流,并参与到任何广告推广、牟利等行为,如果文章在引用方面侵害了您的隐私,请及时和我联系!

邮箱地址:[email protected]

猜你喜欢

转载自blog.csdn.net/congcong0509/article/details/131175983