待字闺中之数组统计分析

题目来源,待字闺中,原创@陈利人 ,欢迎大家继续关注微信公众账号“待字闺中”

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

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

  • 原数组是没有排序的。如果排序了,很简单的。
  • O(1)的空间含义,可以使用变量,但不能开辟数组或者map等来计数。

这个题目,很直接的解法就是两层遍历,O(n^2)的复杂度,O(1)的空间。空间满足了,但是时间没有。 很多类似的题目,都会用XOR的方法,大家仔细想一下,这个题目,可以么?或者这个题目和可以用XOR的题目的差异在哪儿?最直接的就是,每一个数字的重复的次数是不同的。

还有就是以空间换时间的方法,例如用hash map或者数组来计数。时间满足了,但是空间没有满足。 那怎样才能有时间复杂度O(n),空间复杂度O(1)的算法呢?不能开辟新的空间,那么只剩下,重复利用数组A。那么该如何利用数组A呢?

首先,我们介绍一种三次遍历数组的方法,我们都考虑数组从1开始:

  • 第一次遍历:对于每一个A[i] = A[i] * (n+1)
  • 第二次遍历:对于每一个i,A[A[i]/(n+1)]++
  • 第三次遍历:对于每一个i,A[i] %
    (n+1)就是出现次数

A[i]应该出现在A中的A[i]位置,乘以(n+1)、再除以(n+1),很容易的来回变换;第二次遍历,对于A[i]本来所在的位置不断增1,但绝对不对超出(n+1)的,那每一个i出现的次数,就是A[i]对(n+1)取余。

还有一种两次遍历的方法,也是上面的思路:考虑A[i],现在位置是i,如果采用A来计数,它的位置应该是A[i] %
(n+1),找到计数位置,该如何处理这个位置呢?加1么?显然不可以,这里有一个技巧,就是加(n+1),有两个原因

  • 加n可以保证A[i] %
    (n+1)是不变的
  • A数组,最后每一个元素表示为A[i] = x + k*(n+1),其中x

具体代码如下

void statistics1(int* data,int n)//方法一:三次遍历
{
	if(data == NULL || n <= 1)return;
	int i;
	for(i = 1;i <= n;i++)
	{
		data[i] *= (n+1);
	}
	for(i = 1;i <= n;i++)
	{
		data[data[i] / (n+1)]++;
	}
	for(i = 1;i <= n;i++)
	{
		cout << i << " 出现了 " << data[i] % (n+1) <<" 次"<< endl;
	}
}

void statistics2(int* data,int n)//方法二:两次遍历
{
	if(data == NULL || n <= 1)return;
	int i;
	for(i = 1;i <= n;i++)
	{
		data[data[i]%(n+1)] += (n+1);
	}
	for(i = 1;i <= n;i++)
	{
		cout << i << " 出现了 " << data[i]/(n+1) << " 次" << endl;
	}
}

如有问题,请指正

时间: 2024-10-11 15:43:08

待字闺中之数组统计分析的相关文章

leetcode之Find All Numbers Disappeared in an Array

问题来源:Find All Numbers Disappeared in an Array 很久没有刷题了,感觉大脑开始迟钝,所以决定重拾刷题的乐趣.一开始不要太难,选一些通过率高的题目做,然后就看到了这个题目.我有些吃惊,这个题我虽然知道两种解法,但本身还是有难度的,居然通过率这么高.然后就搜索相关网页,看到一个和它很接近的题目<Find All Duplicates in an Array>,然后就释然了.这两个题目有相同的题干,只是问题略微不同,解法有相似之处.估计是因为题号太接近了,会

待字闺中之正数数组内和为指定数字的总数

求正数数组内和为指定数字的合并总数 比如[5, 5, 10, 2, 3] 合并值为 15 : 有4种 : (5 + 10, 5 + 10, 5 + 5 + 2 + 3, 10 + 2 + 3) 分析:有的时候,一个题目不能够立刻想到比较优化的想法,就可以先找到一个解决方案,然后根据方案的不足进行优化.而且这个时候,逆转一下思路,便会柳暗花明.由递归到动态规划,不就是如此么? 我们设定f(index,sum)表示数组从index开始到结束组成的sum的总数.那么,f(index, sum)可以表示

【数据分析&amp;数据挖掘】数组的统计分析

1 import numpy as np 2 3 # 创建一个数组 4 arr = np.array([[1, 2],[3, 4]]) 5 print("arr: \n", arr) 6 7 # 对数组进行统计分析 8 # sum mean std var min max argmin argmax cumsum cumprod 9 # 按照行的方向 10 print("arr的统计和: \n", np.sum(arr, axis=0)) 11 print(&quo

Magic Index 寻找数组中A[i]=i的位置(原题转自微信号待字闺中)

有一个有意思的题目叫做Magic Index:给定一个数组A,其中有一个位置被称为Magic Index,含义是:如果i是Magic Index,则A[i] = i.假设A中的元素递增有序.且不重复,请给出方法,找到这个Magic Index.更进一步,当A中允许有重复的元素,该怎么办呢? 一般情况下这种题目一看没有多复杂的时间复杂度,直接扫描一边数组就好了,O(n),当我们认识读题目的时候发现有个体检没有用到就是这个“数组元素递增有序,不重复”,这句话会不会给我们带来捷径呢,事实是可以的.通常

待字闺中之巧妙排序分析:

题目来源.待字闺中.原创@陈利人 ,欢迎大家继续关注微信公众账号"待字闺中" 排序仅仅有1.2,3三个元素的数组.不能统计1,2.3的个数. 分析:这个题目,虽然也是排序,但却不能使用高速排序的方法.仅仅有三个元素,假设时间复杂度仍旧是O(nlogn).显然不是最好的.那就行使用线性的排序算法,比如计数排序.但是题目中要求,不可以对1,2,3进行统计个数.那该怎样处理呢?请大家看以下的方法,我们首先通过样例来说明: 2 1 1 3 3 2 p1 p2       p3 如果,我们有三个

待字闺中之逆序分析

题目来源,待字闺中,原创@陈利人 ,欢迎大家继续关注微信公众账号"待字闺中" 一个整数,可以表示为二进制的形式,请给出尽可能多的方法对二进制进行逆序操作. 例如:10000110 11011000的逆序为 00011011 01100001 分析:题目中说是一个整数,对它的二进制进行逆序.并不是一个01字符串,或者01的数组.那么我们该如何解决这个问题呢?方法还是比较多的,有的中规中矩.有的非常巧妙.我们要掌握中规中规的方法,见识更多的巧妙的方法.慢慢的,能够举一反三,在遇到新的问题时

待字闺中之Magic Index 分析

给定一个数组A,其中有一个位置被称为Magic Index,含义是:如果i是Magic Index,则A[i] = i.假设A中的元素递增有序.且不重复,请给出方法,找到这个Magic Index.更进一步,当A中允许有重复的元素,该怎么办呢? 没有重复元素的情况 一些同学在遇到这个题目的时候,往往会觉得比较简单.扫描一遍,不就ok了么?O(n)的.很简单呀.可是,大家要注意到,还有一个条件没有用:A中的元素是有序递增的.这个条件,并不是放在这里迷惑大家的,而是有更大的作用的.这个时候,该如何想

MVC与单元测试实践之健身网站(八)-统计分析

?统计分析模块与之前的内容相对独立,用于记录并跟踪各部位围度的变化.还需提供对所作计划的分析,辅助使计划更合理. 一 围度记录 这儿可以记录各项身体围度指标,现在包括体重在内身体上上下下基本全部提供了,虽然貌似用处不大,所以这个界面并不做非空校验,但会有对输入格式的限制,必须是整数或一位小数. 二 围度变化 有了上一步记录的数据后,就可以基于这些数据,以图表的形式直观地反映围度的变化了. a) 模板提供了各种图表插件,最后选择了flotchart,需求比较基础,完全可以满足.用起来也挺方便: 放

待字闺中之最多连续数的子集

题目来源,待字闺中,原创@陈利人 ,欢迎大家继续关注微信公众账号"待字闺中" 给一个整数数组a[]. 找到当中包括最多连续数的子集,比方给:15, 7, 12, 6, 14, 13, 9, 11,则返回: 5:[11, 12, 13, 14, 15] . 分析:最简单的方法是sort然后scan一遍,可是要 o(nlgn) , 有什么 O(n) 的方法吗?网上有人用map或set来做.但map或set的复杂度还是O(nlgn).并查集能够做到O(n),此题用并查集比較简单. 下面參考h