关于数组元素去重问题的大讨论、unique函数的个人理解和实现

这篇文章里,我将专门对如何对数组元素去重进行探讨和解析,希望各位大佬能不吝赐教多加指点,非常感谢!
在上一篇blog中为了解决数组去重的问题,我提出,调用现成的unique函数、或者自己写一个函数来去除重复数,或者是直接定义第二个数组存放然后不断遍历保证不重复。本文将基于上述几种思路,对蓝桥杯“素因子去重“问题,进行深入的探讨,另附代码若干,主要是对不定长的数组进行判断。
题目:
问题描述
  给定一个正整数n,求一个正整数p,满足p仅包含n的所有素因子,且每个素因子的次数不大于1
输入格式
  一个整数,表示n
输出格式
  输出一行,包含一个整数p。
样例输入
1000
样例输出
10
数据规模和约定
  n<=10^12
  样例解释:n=1000=2^353,p=2*5=10
去重方法:
一、直接调用unique函数
①:一般而言,非特殊情况下数组需先进行排序再调用unique函数去重
②:unique函数返回的是去重之后的尾地址。
③:之前踩过的坑:由于返回的是容器的末尾地址,故如果想得到去重后的size,需要减去初始地址(问题得解)。
④必须记住,unique函数是“伪”去重算法,在经过unique函数去重后,该数组的长度仍然与原先一样(网上有重复元素调到元素的后面和用非重复元素覆盖重复元素两种不同解释,经过我的实验,第一种是错的,具体测试方法我贴在了第一种方法的后面,第二种也不全对,因为结果显示应该是数组非重复数字前移覆盖掉了)。
⑤unique函数的实现方法在方法二里会模拟。但想要了解它真正的实现方式还是查看源文件比较好。
原题AC代码:

#include<iostream>
#include<algorithm>
#include<cmath>
#define maxn 100005
#define ll long long
using namespace std;
ll n ,p = 1;
int a[maxn],flag;
int main(void)
{
	cin >> n;
	for(int i = 2; i <= n; i++)
	{
		int OK = 1;
		if(n % i == 0) //判断i是不是n的因子
		{
			for(int j = 2; j <= sqrt(i); j++) //如果是n的因子,则判断i是否为素数 
			{
				if(i % j == 0)
				{
					OK = 0;
					break;
				}
			}
			if(OK)
			{
				n /= i;
				a[flag++] = i;
				i = 2;
			}
		}
	}
	int flag2 = unique (a , a + flag) - a;
	for(int i = 0; i < flag2; i++)
	{
		p *= a[i];
	}
	cout << p;
	return 0;
}

关于unique函数,具体举个例子:

#include <iostream>
#include <algorithm> //根据网上很多资料unique的头文件是#include<iostream>,但在dev5.11中必须要添加上algorithm头文件才能使用,以下代码均是在dev5.11中测试通过
using namespace std;
int main()
{
	int a[8] = {1,1,2,3,5,6,8,7}; //为了体现多种情况,这个数组有重复,也不是完全按照顺序排列的
	int len; //因为一般用到unique函数一般都是为了求出最后一个不重复数字的位置,故len(length)标志
	sort(a,a+8);
	len = unique(a,a+8) - a;
	cout << len;
	return 0;
}

输出的结果是:在这里插入图片描述
验证方法:

#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
	int a[8] = {1,1,2,3,5,6,8,7}; //为了体现多种情况,这个数组有重复,也不是完全按照顺序排列的
	int ans = 0, ans1 = 0 , ans2 = 0 , ans3 = 0 , ans4 = 0 , ans5 = 0 , ans6 = 0 , ans7 = 0,len; //因为一般用到unique函数一般都是为了求出最后一个不重复数字的位置,故len(length)标志
	sort(a, a + 8);
	len = unique(a,a + 8) - a;
	for(int i = 0; i < len; i++)
	{
		if(i < len - 1){
			cout << a[i] << " ";
		}
		else{
			cout << a[i] << endl;
		}
	}
	for(int i = 0; i < 8; i++)
	{
		if(a[i] == 1){
			ans += 1;
		}
		if(a[i] == 2){
			ans2 += 1;
		}
		if(a[i] == 3){
			ans3 += 1;
		}
		if(a[i] == 5){
			ans4 += 1;
		}
		if(a[i] == 6){
			ans5 += 1;
		}
		if(a[i] == 7){
			ans6 += 1;
		}
		if(a[i] == 8){
			ans7 += 1;
		}
	}
	cout << "1:" << ans << endl
	     << "2:" << ans2 << endl
	     << "3:" << ans3 << endl
	     << "5:" << ans4 << endl
	     << "6:" << ans5 << endl
	     << "7:" << ans6 << endl
	     << "8:" << ans7 << endl;
	return 0;
}

程序运行结果:在这里插入图片描述

二、自己写一个函数来去除重复
本质上来说就是用自己的函数实现类似于unique函数的功能。
代码如下(有注释,很好理解):

留个坑,回头填上。。、

三、直接定义第二个数组存放不重复的数字
代码如下

#include<iostream>
#include<algorithm>
#include<cmath>
#define maxn 100005
#define ll long long
using namespace std;
ll n ,p = 1;
int a[maxn],b[maxn],flag,flag2 = 0;
int judgenumber(int n);
int main(void)
{
	cin >> n;
	for(int i = 2; i <= n; i++)
	{
		int OK = 1;
		if(n % i == 0) //判断i是不是n的因子
		{
			for(int j = 2; j <= sqrt(i); j++) //如果是n的因子,则判断i是否为素数 
			{
				if(i % j == 0)
				{
					OK = 0;
					break;
				}
			}
			if(OK)
			{
				n /= i;
				a[flag++] = i;
				i = 2;
			}
		}
	}
	for(int i = 0; i < flag; i++)
	{
		if(judgenumber(a[i])){
			b[flag2] = a[i];
			flag2++;
		}
	}
	for(int i = 0; i < flag2; i++)
	{
		p *= b[i];
	}
	cout << p;
	return 0;
}

int judgenumber(int n)
{
	for(int i = 0; i < flag2; i++)
	{
		if(b[i]==n)
		{
			return 0;
		}
	}
	return 1;
}

另外附上https://blog.csdn.net/pipinuan/article/details/52934580,这篇blog写的很不错,但相对本篇理解起来难度要稍微大一点,在本blog吃透的情况下可以考虑进阶哦

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值