数值相等_LeetCode基础算法题第168篇:唯一的数值次数

技术提高是一个循序渐进的过程,所以我讲的leetcode算法题从最简单的level开始写的,然后到中级难度,最后到hard难度全部完。目前我选择C语言,Python和Java作为实现语言,因为这三种语言还是比较典型的。由于篇幅和精力有限,其他语言的实现有兴趣的朋友请自己尝试。

如果有任何问题可以在文章后评论或者私信给我。

如果有朋友希望我讲些其他话题,请在评论区留言或者私信给我。

持续分享,敬请关注。

LeetCode 1207. 唯一的数值次数(Unique Number of Occurrences)

问题描述:

给定一个整数数组arr,编写一个函数,当且仅当该数组中每个值的出现次数是唯一的时才返回true。

注:

  • 1 <= arr.length <= 1000;
  • -1000 <= arr[i] <= 1000;

示例:

ba6a11fd1d35f57b724624616b3e071e.png

C语言实现:

一般思路是,创建一个长度为2001的数组count,用来统计arr中不同值出现的数量。再创建一个长度是arr.length+1的数组 bits。遍历count,针对每一个元素e,如果bits[e] > 0, 返回false。否则 bits[e] += e;遍历结束,没问题就返回true。

这个思路实现简单,但是有一个问题:不管arr的长度是多少,如果arr中的数值次数都是唯一的,就需要遍历count 2001次。

我们期望能找到一个算法,在计算的时候是要依赖arr的长度,毕竟arr的长度是小于等于2001的。

我们可以对上面的算法做一些改造,我们将bits定义为长度为63的无符号整型,这么bits可以作为一个长度为2016的bitmap(63*32=2016),则它就可以用bit位标记arr中是否存在某个数。

这种方法我们在前面的题目中多次用的,它的好处是节省空间,但是有时候也会对时间复杂度有优化作用,一会就能看到。

接下来,我们遍历arr,开始在bits完成这个bit标注。由于arr中的数的数值范围是[-1000,1000],因此我们将它们都增加1000,变成[0,2000],以使得bits可以表示它们。这就是为什么bits的长度是63。

在遍历的同时,统计不同数值出现的次数。

我们回头看,会发现,其实bits就类似map中的key,而count就是map中的value。

然后我们新建一个长度为1+arr.length的整型数组 count_map,这个依然是一个bitmap,它用来鉴别是否存在重复数量。

然后我们遍历bits,这是和上一个算法最不同的地方。遍历bits就类似遍历map中的key。这里我们通过位操作,获取arr中每一个不同的值(代码中的j),然后依次来查询count中该值出现的次数。

最后,我们依然通过位操作来判断count_map中该次数是否已经出现,如果出现就返回false,否则设置count_map。

我们会发现这个算法虽然要复杂一点,但是没有对count遍历,对bits的遍历其实也是线性的,遍历的时间长短由arr中存在多少个不同值决定,所以时间复杂度是O(arr.length)。

详细代码如下:

5a5f6d40df42d0ac4443d9678c9230b4.png

需要提醒的是,bits需要定义成无符号整型,因为普通int,最前面一位是符号位,并不能表示具体值,当遇到1<<31操作时会出错,且移位操作时,数值1也需要强制转换成无符号整型。

89c83521983d9b928dfa68e3148be50f.png

Java语言实现:

Java 的实现和C语言的实现一致,需要提醒的是,java中没有无符号整型,所以一个整型我们只能用后31位做bitmap,所以bits长度定义位65,后续的位操作也是用31而不是32。

代码如下:

be47eb26b8928e4b82410348bc366d91.png
75cd34cbf5609429ba11a143ee2f026b.png

Python语言实现:

Python 的实现,我觉得的简洁才是王道。我们可以用Counter直接完成计数,最后比较Counter对象的key和value的长度是否相等即可。

代码如下:

383248e7b8cef282063c7e2ca4334fdb.png
b20f6f2b2f4b1697034a174da1a18d85.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值