《代码随想录学习笔记》---数组【移除元素】

一、数组移除难处

因为数组顺序存储的特性,要求删除数组中【指定数值】并不像链表一样简便,需要将其后续存储内容顺次前移覆盖。

抱着玩玩leetcode打发时间的心态,我尝试了一共四种写法

二、具体解法

1.暴力法

用两重循环,外层循环用于检查是否存在【nums[i]==val】,一旦发现,进入内层循环,将后续元素全部顺次前移一位,直到数组末尾

时间复杂度为O(n^2),空间复杂度O(1)

没啥好说的,直接上代码

int remove(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--;
				size--;
			}
		}
		return size;
	}

2.存储法

如果能有一个【笔记本】一样的东西,让我在遍历过程中把【我要的】元素记录下来,就可以省去两遍遍历

新开一个temp数组,将所有不重复元素存储进去,这样时间复杂度降到O(n),但相应的空间复杂度达到O(n

int remove(vector<int>& nums, int val)
	{
		int size = nums.size();
		vector<int> newnums;
		for (int i = 0; i < size; i++)
		{
			if (nums[i] != val)
			{
				newnums.push_back(nums[i]);
			}
		}
		nums = newnums;
		return nums.size();
	}

3.存储法pro

时空复杂度与【存储法】没有本质区别,只是并不新申请一个vector,而是直接把所需元素记录在原有vector尾部,最后统一复写

int remove(vector<int>& nums, int val)
	{
		int size = nums.size();
		int cnt=0;
		for (int i = 0; i < size; i++)
		{
			if (nums[i] != val)
			{
				nums.push_back(nums[i]);
				cnt++;
			}
		}
		for (int i = 0; i < cnt; i++)
		{
			nums[i] = nums[size++];
		}
		return cnt;
	}

4.快慢指针

是不同于前三种的较优解法,设计两个指针——慢指针+快指针,快指针随着for循环逐次更新,慢指针只有在写入【我要的数】后才进行更新

也正因如此,慢指针的数值就对应着新数组的大小

时间复杂度O(n),空间复杂度O(1)

上代码:

int remove_doublep(vector<int>& nums, int val)
	{
		int size = nums.size();
		int slowidx = 0;
		for (int fi = 0; fi < size; fi++)
		{
			if (val != nums[fi])
			{
				nums[slowidx++] = nums[fi];
				//cout << slowidx << endl;
			}
		}
		return slowidx;
	}

三、LeetCode平台测试结果(题号27)

暴力法:

 存储法:

存储法pro:

 长短指针:

 结果显示,在leetcode平台的113个case情况下,暴力法和存储法表现一般,且存储法有明显的空间性能劣势。

但【存储法pro】和【长短指针】都能达到4ms以下的解题时间,甚至【存储法pro】的空间利用更优,这种情况或许与vector的存储特性有关。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值