从数组删除重复项用c语言,目标C中从NSMutableArray中删除重复值的最佳方法-C?

是的,使用NSSet是一种明智的方法。

为了补充Jim Puls的回答,这里有一种在保留订单的同时剥离副本的替代方法:// Initialise a new, empty mutable array NSMutableArray *unique = [NSMutableArray array];for (id obj in originalArray) {

if (![unique containsObject:obj]) {

[unique addObject:obj];

}}

它基本上与Jim的方法相同,但将唯一项复制到一个新的可变数组中,而不是从原始数组中删除重复项。这使得在具有大量重复(不需要复制整个数组的副本)的大型数组的情况下,它的内存效率略高一些,而且在我看来,它的可读性更高一些。

请注意,在任何一种情况下,都要检查目标数组中是否已经包含了项(使用containsObject:在我的例子中,或者indexOfObject:inRange:(在Jim‘s中)不能很好地扩展到大型数组。这些检查在O(N)时间内运行,这意味着如果将原始数组的大小增加一倍,那么每张支票要跑两倍的时间。由于您正在对数组中的每个对象进行检查,您还将运行更多的这些更昂贵的检查。整个算法(我的和Jim的)运行在O(N)中2)时间,随着原始数组的增长,时间很快就会变得昂贵。

要将其降到O(N)时间,您可以使用NSMutableSet存储已添加到新数组中的项的记录,因为NSSet查找是O(1)而不是O(N)。换句话说,无论集合中有多少元素,检查一个元素是否是NSSet的成员都需要相同的时间。

使用这种方法的代码如下所示:NSMutableArray *unique = [NSMutableArray array];NSMutableSet *seen = [NSMutableSet set];for (id obj in originalArray) {

if (![seen containsObject:obj]) {

[unique addObject:obj];

[seen addObject:obj];

}}

不过,这看起来还是有点浪费;当问题表明原来的数组是可变的时,我们仍然在生成一个新数组,因此我们应该能够将它降到适当的位置,并节省一些内存。就像这样:NSMutableSet *seen = [NSMutableSet set];NSUInteger i = 0;while (i 

id obj = [originalArray objectAtIndex:i];

if ([seen containsObject:obj]) {

[originalArray removeObjectAtIndex:i];

// NB: we *don't* increment i here; since

// we've removed the object previously at

// index i, [originalArray objectAtIndex:i]

// now points to the next object in the array.

} else {

[seen addObject:obj];

i++;

}}

更新Yuri Niyazov指出我的最后一个答案实际上是O(N)2)因为removeObjectAtIndex:可能在O(N)时间内运行。

(他说“可能”是因为我们不确定它是如何实现的;但一个可能的实现是,在删除索引X处的对象之后,该方法循环遍历从索引X+1到数组中的最后一个对象的每个元素,然后将它们移动到前一个索引。如果是这样的话,那就是O(N)的性能。

那么,该怎么办呢?这要视情况而定。如果你有一个很大的数组,而且你只需要少量的重复,那么就地去复制就可以正常工作了,这样你就不必构建一个重复的数组了。如果您有一个数组,您需要大量的重复,那么构建一个单独的、去欺骗的数组可能是最好的方法。这里的方法是,大O表示法只描述一个算法的特性,它不会确切地告诉你哪种方法对任何给定的情况都是最好的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值