数组计数

原题

给定数组A,大小为n,数组元素为1到n的数字,不过有的数字出现了多次,有的数字没有出现。请给出算法和程序,统计每个数字出现了多少次。能够在O(n)的时间复杂度,O(1)的空间复杂度要求下完成么?

在原文上做了点修改,原文链接:http://mp.weixin.qq.com/s?__biz=MjM5ODIzNDQ3Mw==&mid=200446711&idx=1&sn=09b2db28fcfa289cfb69d60f066d1d91#rd

分析

这个题目,是有一定技巧的。技巧是需要慢慢积累,待经验多了之后,可以灵感或者直觉,就产生了技巧。如果不知道技巧,那该怎么办呢?

在开始分析之前,说明两个问题:

  • 原数组是没有排序的。如果排序了,很简单的。

  • O(1)的空间含义,可以使用变量,但不能开辟数组或者map等来计数。

这个题目,很直接的解法就是两层遍历,O(n^2)的复杂度,O(1)的空间。空间满足了,但是时间没有。

很多类似的题目,都会用XOR的方法(异或吗?),大家仔细想一下,这个题目,可以么?或者这个题目和可以用XOR的题目的差异在哪儿?最直接的就是,每一个数字的重复的次数是不同的。

还有就是空间换时间的方法,例如用hash map或者数组来计数。时间满足了,但是空间没有满足。

那怎样才能有时间复杂度O(n),空间复杂度O(1)的算法呢?不能开辟新的空间,那么只剩下,重复利用数组A(因为数组中所有元素都不大于n,所以可以好好利用这一特点)。那么该如何利用数组A呢?

要知道每一个数字出现的次数,而且只能遍历一次,这种情况下当一个数字出现的时候,就要对它进行标记。比如考虑如下数组A[6],n=6:

012345
231442
怎么标记A[0]=2,这个2出现了一次呢,这时候要想到用对应的下标来识别元素(元素=下标+1),因为这样才是唯一对应的。所以2出现一次,下标为1的值(3)就加n;以此类推,最后统计每个下标对应的值加了多少个n就表示这个这个下标对应的元素(i+1)出现了几次。

代码如下:时间复杂度o(n),空间复杂度o(1)

void count(int [] A, int n){
	for(int i=0;i<n;++i){
		A[A[i]%n-1]+=n;
	}
	for(int i=0;i<n;++i){
		cout<<"i+1出现了"<<A[i]/n<<"次\n";
	}
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值