2.1.2从排序阵列II中删除重复项

5 篇文章 1 订阅

2.1.2从排序阵列II中删除重复项

描述

“删除重复项”的后续操作:如果最多允许重复两次怎么办?例如,给定排序数组A=[1,1,1,2,2,3],您的函数应该返回长度=5,而A现在为[1,1,2,2,3]

分析

加一个变量记录一下元素出现的次数即可。这题因为是已经排序的数组,所以一个变量即可解决问题。如果是没有排序的数组,则需要引入一个hashmap来记录出现的次数

#include<iostream>
#define SIZE 10
using namespace std;
void del(int* a, int* lenth, int j);
int test(int* a, int* length);
int main()
{
	int a[SIZE] = { 1,1,1,1,2,2,2,3,3,4 };
	int lenth = 10;
	cout<<"长度为" << test(a, &lenth)<<endl;
	cout << "更改后数组为" << endl;
	for (int i = 0; i < lenth; i++)
		cout << a[i]<<" ";
	return 0;
}
//允许重复最多2次,这里咱们先用传统的C语言进行实现,即不使用任何的STL。
//思路,使用双指针法则外加一个标志位,例如:a=[1,1,1,2,2,3,3,3]
//指针i指向第一个元素,指针j指向第二个元素,flag标志位表示之前这两个双指针的元素是相等的
//第一次循环 i=0 j=i 此时a[i]==a[j],将flag置为1。再将i与j进行加一操作
//此时i=1,j=2,且a[i]==a[j],判断flag==1此时删除j位置的数字,继续执行循环
//此时i=1,j=2,且a[i]为1 != a[j]为2,此时将flag置为0,继续循环
//循环次数为数组的长度-1
int test(int* a, int *length)
{
	if (*length < 2)
		return *length;
	int i = 0;
	int j = 1;
	int flag = 0;
	for (size_t k = 0; k < *length - 1; k++)
	{
		if (a[i] == a[j] && !flag)
		{
			flag = 1;
			i++;
			j++;
		}
		else if(a[i] == a[j] && flag)
		{
			del(a, length, j);

		}
		else
		{
			flag = 0;
			i++;
			j++;
		}
	}
	return *length;
}

void del(int* a, int* lenth, int j)
{
	for (int i = j; i < *lenth; i++)
	{
		a[i] = a[i + 1];
	}
	(*lenth)--;
}

代码1
//时间复杂度O(n)空间复杂度O(1)

class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if (nums.size() <= 2) return nums.size();
int index = 2;
for (int i = 2; i < nums.size(); i++){
if (nums[i] != nums[index - 2])
nums[index++] = nums[i];
}
return index;
}
};

代码2
下面是一个更简洁的版本。上面的代码略长,不过拓展性更好一点,例如将occur<2改成occur<3,就变成了允许重复最多3次。

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

class Solution {
public:
int removeDuplicates(vector<int>& nums) {
const int n = nums.size();
int index = 0;
for (int i = 0; i < n; ++i) {
if (i > 0 && i < n - 1 && nums[i] == nums[i - 1] && nums[i] == nums[i + 1])
continue;
nums[index++] = nums[i];
}
return index;
}
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值