返回在NSArray中仅出现一次的第一个数字

时间:2015-03-22 18:11:57

标签: ios objective-c algorithm nsarray

我想知道这个问题的最佳或最合适的方法:给出一个数字列表示例[2,3,4,2,3],返回仅出现一次的第一个数字清单。

我已经遵循了一些算法方法并提出了这个方法,但不确定Objective-C中是否有任何内置的辅助函数可以让我以更好的性能执行此操作。

如果没有内置解决方案,是否可以对我的方法或任何其他可能在性能方面更好的解决方案进行任何改进?

这是我更新的解决方案:
进行测试:

#import "NSArray+Addons.h"

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    NSArray<NSNumber *> *array = @[@(2), @(7), @(3), @(2), @(3), @(2), @(7), @(3), @(2), @(3), @(4), @(7), @(5), @(5), @(9)];
    NSLog(@"Unique number: %@", [array firstUniqueNumber]);
}

@end

NSArray类别:

#import "NSArray+Addons.h"
#import "NSMutableDictionary+Addons.h"

@implementation NSArray (Addons)

- (NSNumber *)firstUniqueNumber
{
    if (!self.count)
    {
        return nil;
    }

    NSMutableDictionary<NSNumber *, NSNumber *> *myUniqueNumbers = [[NSMutableDictionary alloc] init];

    return [myUniqueNumbers uniqueValueFromArray:self];
}

@end

NSMutableDictionary类别:

#import "NSMutableDictionary+Addons.h"

@implementation NSMutableDictionary (Addons)

- (NSNumber *)uniqueValueFromArray:(NSArray<NSNumber *> *)array
{
    if (!array.count)
    {
        return nil;
    }

    for (NSNumber *number in array)
    {
        if (!self[number])
        {
            self[number] = [NSNumber numberWithInteger:1];
        }
        else
        {
            NSInteger count = [self[number] integerValue];
            count++;
            self[number] = [NSNumber numberWithInteger:count];
        }
    }

    return [self uniqueNumberWithArray:array];
}


- (NSNumber *)uniqueNumberWithArray:(NSArray<NSNumber *> *)array
{
    if (!array.count)
    {
        return nil;
    }

    NSNumber *uniqueNumber = nil;

    for (NSInteger index = array.count - 1; index > 0; index--)
    {
        NSNumber *key = array[index];

        if (self[key] && [self[key] integerValue] == 1)
        {
            uniqueNumber = key;
        }
    }

    return uniqueNumber;
}

@end

3 个答案:

答案 0 :(得分:4)

NSCountedSet* set = [[NSCountedSet alloc] initWithArray:array];
NSUInteger index = [array indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop){
    return [set countForObject:obj] == 1;
}];
return index == NSNotFound ? nil : [array objectAtIndex:index];

答案 1 :(得分:1)

此问题可以减少到element distinctness problem,因此没有使用散列和额外空间的线性时间解决方案。

O(n)时间平均+空间的一个简单解决方案是:

  1. 构建基于哈希的数据直方图,将每个值映射到其出现次数。
  2. 在数组中查找其直方图中的值为1的第一个数字。
  3. 伪代码:

    map = new hashmap
    for each element x:
       if map contains x is a key:
           map.put(x,map.get(x)+1)
       else:
           map.put(x,1)
    for each element x in array:
       if map.get(x) == 1:
           return x
    //if reached here - no distinct element
    

    示例:

    array = [2, 3, 4, 2, 3]
    create histogram: {[2=2] [3=2], [4=1]}
    iterate the array:
       check 2, it has value of 2 in histogram. continue
       check 3, it has value of 2 in histogram. continue
       check 4, it has value of 1 in histogram. Return it and finish.
    

答案 2 :(得分:0)

-(NSNumber *)returnFirstUniqueFromArray: (NSArray *)array{

    //put the numbers in a set
    NSCountedSet *numbers = [[NSCountedSet alloc] initWithArray:array];
    for(NSNumber *number in array){
        //if it only occurs once return
        if([numbers countForObject:number]==1) return number;
    }

    return nil;

}

他们关键在这里你需要一个很好的方法来跟踪事情的发生次数,所以利用NSCountedSet的“计数”方法。会告诉你物体发生了多少次。