统计数组中各元素出现次数

部署运行你感兴趣的模型镜像

1.问题描述

        给定一大小为N的整数数组,其元素取值范围为[1,N],请统计各元素出现的次数,并要求时间复杂度为O(n),空间复杂度为O(1)。


2.思路

       若没有空间的限制,则可直接开辟一个大小等于元素最大值的数组对各元素进行统计,并且顺带还进行了时间复杂度为O(n)的排序(比快速排序还快哦)。

       统计n个元素出现的次数,每个元素对应一个次数信息需要存储,那么就需要n个空间;而现在不让开辟新的n个空间,这些信息又必须要记录,那你说该放在哪?当然是原数组中啰!

       不过问题又来了,原数组中的值岂不是会被覆盖掉?好吧,可以先把数组中原来的值拿出来后放跟次数相关的信息就没问题了。对于拿出来的这个值,必须即拿即用(不然堆积起来又要n个空间来存储),由于元素取值范围为[1,N],因此可以将这个值当作数组的索引来访问下个元素(记得-1)。

       还有个问题,若像数字5出现了2次,第一次遇到数字5时,将a[4]中原来的值取出用来访问下一个元素并将a[4]清零后+1表示5已经出现过1次了;第二次遇到数字5时问题就来了,不能将现在a[4]中的值取出用来访问下个元素,只能将a[4]加1表示又遇到5了。也就是说一个元素没被访问过和被访问过两种状态得区别对待,那么,怎么知道元素有没有被访问过呢?之前每个元素需要记录次数相关信息,现在每个元素又要体现有没有被碰过,如何让一个值体现这两种属性呢?我们知道一个数除了大小外还有正负这个属性,因此这里便将被访问过的元素设为负值(因为原数组中元素均为正值且没被碰过),于是第一次遇到某个元素时现将它清零后-1,以后每遇到一次就-1。最后将值取反便得到各元素对应的出现次数。

       最后还有一个问题,就是当再次访问某个元素时,由于其值为负表示其出现的次数,就没办法从中得到访问下一元素所需的信息,程序没办法进行下去!因此,这个时候需要手动指定下一个访问的元素是谁,当然是从头到尾全部指定一遍(尽管被指定的元素可能之前已经被访问过了,没关系,再指定下一个就好了),既保证所用元素都被至少访问过一次又可以使整个过程终止。例如,第一次指定a[0],第二次指定a[1],...,直到a[n-1]为止。还请注意的是,通过手动指定而访问到的元素只需要将值清零而不用-1,因为没有数字指向它,当然出现的次数也就是0啰!

题外话:一个问题之所以不像它看上去那么简单,除了需要奇葩的想法外,就是要处理各种特殊的状况。


3.代码   

#include <stdio.h>
#define N 7

void elementCounter(int array[],int n);

int main(void)
{//测试用例
  int array[N]={5,5,2,4,1,7,5};

  elementCounter(array,N);
  
  return 0;
}

void elementCounter(int array[],int n)
{
  int index;//访问下一个元素用的索引
  int flag;//标志此次访问是否为手动指定的
  int temp;
  int i;
//统计元素出现次数
  for(i=0,index=0,flag=1;i<n; )//因为手动指定从array[0]开始,flag设为1
  {
	if(array[index]>0)//某元素第一次被访问
	{
	  temp=array[index];
	  array[index]=flag-1;//若是被手动指定访问到的,则flag=1,其值为0不算其出现过
	  index=temp-1;//自动指定下一个访问元素
	  flag=0;//因为是第一次被访问,其值可以用来访问下个元素,不需要手动指定
	}
	else//某元素不是第一次被访问
	{
	  array[index]=flag-1+array[index];////若是被手动指定访问到的,则flag=1,其出现次数不变
	  index=++i;//手动指定下个访问元素
	  flag=1;//标志下一次访问为手动指定的
	}
  }
//打印元素出现次数
  for(i=0;i<N;i++)
  {
	if(array[i]!=0)//不打印没出现过的
	printf("数字%d出现%d次\n",i+1,-array[i]);
  }
}






您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

在 JavaScript 中,有多种方法可以统计数组中各元素出现的次数,以下是几种常见的实现方式: ### 方法一:使用 `for` 循环和对象 ```javascript var arr = [2, 3, 5, 6, 7, 1, 3, 4, 2, 4, 3]; let obj = {}; for (let i = 0; i < arr.length; i++) { if (obj[arr[i]]) { obj[arr[i]] += 1; } else { obj[arr[i]] = 1; } } console.log(obj); ``` 此方法通过 `for` 循环遍历数组,检查元素是否已存在于对象中,若存在则次数加 1,不存在则初始化为 1 [^2]。 ### 方法二:使用 `reduce` 方法 ```javascript var names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice']; var countedNames = names.reduce((obj, name) => { if (name in obj) { obj[name]++; } else { obj[name] = 1; } return obj; }, {}); console.log(countedNames); ``` 该方法使用 `reduce` 方法对数组进行迭代,通过累加器对象统计元素出现次数 [^4]。 ### 方法三:使用 `forEach` 方法 ```javascript var arr = [2, 3, 5, 6, 7, 1, 3, 4, 2, 4, 3]; let obj = {}; arr.forEach(item => { if (obj[item]) { obj[item]++; } else { obj[item] = 1; } }); console.log(obj); ``` 此方法使用 `forEach` 方法遍历数组,同样是检查元素是否存在于对象中,存在则次数加 1,不存在则初始化为 1。 ### 方法四:字符串转换为数组统计 ```javascript var str = 'abfeacmwwxzyyydsmafe'; var arr = []; for (var i = 0; i < str.length; i++) { arr.push(str.charAt(i)); } var newarr = []; var obj = {}; arr.forEach(function (item) { if (newarr.indexOf(item) == -1) { newarr.push(item); obj[item] = 0; } }); newarr.forEach(function (item) { arr.forEach(function (item1) { if (item == item1) { obj[item]++; } }); }); console.log(obj); ``` 该方法先将字符串转换为数组,然后去重,最后统计每个元素出现的次数 [^5]。
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值