马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本文为《代码随想录》的学习笔记,原文链接:代码随想录
题目
原题链接:
27. 移除元素
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值即是 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。
假设 nums 中不即是 val 的元素数量为 k,要通过此题,您需要执行以下操纵:
- 更改 nums 数组,使 nums 的前 k 个元素包含不即是 val 的元素。nums 的其余元素和 nums 的巨细并不紧张。
- 返回 k。
示例 1:
- <strong>输入:</strong>nums = [3,2,2,3], val = 3
- <strong>输出:</strong>2, nums = [2,2,_,_]
- <strong>解释:</strong>你的函数函数应该返回 k = 2, 并且 nums<em> </em>中的前两个元素均为 2。
- 你在返回的 k 个元素之外留下了什么并不重要(因此它们并不计入评测)。
复制代码 示例 2:
- <strong>输入:</strong>nums = [0,1,2,2,3,0,4,2], val = 2
- <strong>输出:</strong>5, nums = [0,1,4,0,3,_,_,_]
- <strong>解释:</strong>你的函数应该返回 k = 5,并且 nums 中的前五个元素为 0,0,1,3,4。
- 注意这五个元素可以任意顺序返回。
- 你在返回的 k 个元素之外留下了什么并不重要(因此它们并不计入评测)。
复制代码 提示:
- 0 <= nums.length <= 100
- 0 <= nums <= 50
- 0 <= val <= 100
题解
为适应机试情况,使用Dev C++编译
输入说明:n=数组元素个数,nums数组元素,一个值val
输出说明:不即是 val 的元素数量为 k,nums的剩余元素
示例一:
输入:4 3 2 2 3 3
输出:
2
2 2
示例二:
输入:8 0 1 2 2 3 0 4 2 2
输出:
5
0 1 3 0 4
方法一:使用erase() 函数
erase() 说明
erase可以删去容器中指定位置的元素,容器的size(巨细)会改变,但是容器的容量稳定。
- //删除a向量中全部元素
- a.erase(a.begin(), a.end());
- //删除a向量中下标0-2共三个元素
- a.erase(a.begin(), a.begin()+3);
复制代码 测试程序:
- int main(){
- for(int i = 1; i < 5; i++) a.push_back(i); //输入数据
- cout << "使用erase删除前:" ;
- for(int i = 0; i < a.size(); i++){
- cout << a[i] << " ";
- }
- cout << endl;
- a.erase(a.begin(), a.begin() + 3);
- cout << "使用erase删除后:";
- for(int i = 0; i < a.size(); i++){
- cout << a[i] << " ";
- }
- return 0;
- }
- //输出:
- 使用erase删除前:1 2 3 4 5
- 使用erase删除后:4 5
复制代码 留意:erase删除nums中元素后,由于后面的元素均向前移动了一个位置,因此需要i--使指针指向原来的i-1元素,如许在下一轮遍历时指针才会指向原来的i+1元素,否则会出现遗漏。
使用Dev C++编译
- #include <bits/stdc++.h>
- using namespace std;
- vector<int>nums;
- int removeElement(vector<int>& nums, int val)
- {
-
- int k=0;
- int length=nums.size();
- for(int i=0;i<length;i++)
- {
- if(nums[i]==val)
- {
- nums.erase(nums.begin()+i);
- i--;//erase数组中的i元素后,后面的元素均向前移了一位,因此需要i--,指针指向原来i-1元素
- length--;//erase删去一个元素,length减一
- }
- }
- k=nums.size();
- return k;
-
- }
- int main()
- {
- int n,val;
- cin>>n;
- for(int i=0;i<n;i++)
- {
- int ans;
- cin>>ans;
- nums.push_back(ans);
- }
- cin>>val;
-
- int k = removeElement(nums, val); // 调用你的实现
- cout<<k<<endl;
- for(int i=0;i<k;i++)
- {
- cout<<nums[i]<<" ";
- }
- return 0;
- }
复制代码 在LeetCode中运行
- class Solution {
- public:
- int removeElement(vector<int>& nums, int val) {
- int k = 0;
- int length = nums.size();
- for (int i = 0; i < length; i++) {
- if (nums[i] == val) {
- nums.erase(nums.begin() + i, nums.begin() + i + 1);
- i--;
- length--;
- }
- }
- k = nums.size();
- return k;
- }
- };
复制代码
时间复杂度:O(n^2)
erase()方法的时间复杂度为O(n)
空间复杂度:O(1)
方法二:暴力解法
本质上头脑与前一种雷同。
这个题目暴力的解法就是两层for循环,一个for循环遍历数组元素 ,第二个for循环更新数组。
在LeetCode中运行
- // 时间复杂度:O(n^2)
- // 空间复杂度:O(1)
- class Solution {
- public:
- int removeElement(vector<int>& nums, int val) {
- int size = nums.size();
- for (int i = 0; i < size; i++) {
- if (nums[i] == val) { // 发现需要移除的元素,就将数组集体向前移动一位
- for (int j = i + 1; j < size; j++) {
- nums[j - 1] = nums[j];
- }
- i--; // 因为下标i以后的数值都向前移动了一位,所以i也向前移动一位
- size--; // 此时数组的大小-1
- }
- }
- return size;
- }
- };
复制代码
方法三:双指针法
双指针法(快慢指针法):通过一个快指针和满指针在一个for循环下完成两个for循环的工作。
定义快慢指针
- 快指针:寻找新数组的元素,新数组就是不含有目的元素的数组
- 满指针:指向更新 新数组下标的位置
在编写代码时需留意i++与++i的区别:
通俗地讲,i++是先赋值再自增,++i是先自增再赋值
在LeetCode中运行
- class Solution {
- public:
- int removeElement(vector<int>& nums, int val) {
- int slowIndex = 0;
- int length = nums.size();
- for (int fastIndex = 0; fastIndex < length; fastIndex++) {
- if (nums[fastIndex] != val) {
- nums[slowIndex++] = nums[fastIndex];
- //相当于
- //nums[slowIndex]=nums[fastIndex];
- //slowIndex++;
- }
- }
- return slowIndex;
- }
- };
复制代码
留意这些实现方法并没有改变元素的相对位置!
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |