如何在O(1)中完成此

时间:2018-01-05 15:52:40

标签: objective-c big-o little-o

我刚从一家公司接受了面试测试,我轻松地完成了它,但他们说我的功能在o(n)。继承人提出问题

  

使用以下方法编写IntegerTracker类:​​

track(int) - Receives an integer for tracking. 
get_max() - Returns the max (int) of all integers seen so far. 
get_min() - Returns the min (int) of all integers seen so far. 
get_mean() - Returns the mean (float) of all integers seen so far.
get_mode() - Returns the mode (int) of all integers seen so far.

确保每个方法(包括跟踪)以恒定时间运行(O(1)时间复杂度)。

这就是我完成它的方式

- (instancetype)init{
    if(self == [super init]){
        self.numbers = [[NSMutableArray alloc]init];
    }
    return self;
}

- (void)trackInt:(int)number{
    [self.numbers addObject:[NSNumber numberWithInt:number]];
}

- (int)getMax{

    NSNumber *max = [self.numbers valueForKeyPath:@"@max.self"];
    return [max intValue];
}

- (int)getMin{

    NSNumber *min = [self.numbers valueForKeyPath:@"@min.self"];
    return [min intValue];
}

- (float)getMean{
    NSNumber *average = [self.numbers valueForKeyPath:@"@avg.self"];
    return [average floatValue];
}
- (int)getMode{

    int maxCount = 0;
    int value = 0;
    NSMutableDictionary *mode = [[NSMutableDictionary alloc]init];
    for(NSNumber *n in self.numbers){
        int currentCount = [[mode objectForKey:n.stringValue]intValue];
        currentCount++;
        [mode setObject:@(currentCount) forKey:n.stringValue];
        if(maxCount < currentCount){
            maxCount = currentCount;
            value = [n intValue];
        }
    }

    return value;
}

有人可以告诉我如何在O(1)中完成此操作。我已经放弃了原因,所以不要认为你给我一个面试的答案。我不打算在那里工作。我只是想知道如何在不迭代数组的情况下解决这个问题。

2 个答案:

答案 0 :(得分:6)

我认为你必须以不同的方式写trackInt:

- (void)trackInt:(int)number{
    if (number > self.max) {
        self.max = number;
    }
    // different logic for the other desired outcomes
}

这样,无论何时添加新数字,您都可以使用简单的计算来确定恒定时间内的max(以及其他值)。

实际的max方法如下:

- (int) getMax { return self.max; }

模式,平均等增量计算的逻辑看起来有点不同,但您可能永远不必使用numbers数组,但更可能有count和{ {1}}要跟踪。

对于sum,您可以保留一个字典,将mode映射到计数器上,该计数器会跟踪该数字的发生频率。此外,您还可以存储发生次数最多的当前计数number如果新增加的计数器大于存储的计数器,则您有一个新的maxNumberCount值,当前存储/返回mode并相应地更改number。< / p>

答案 1 :(得分:4)

使函数在O(1)中工作意味着它们内部不能进行任何迭代。实际上没有理由存储这些数字。您只需要存储统计信息:

@property (nonatomic) NSInteger min;
@property (nonatomic) NSInteger max;
@property (nonatomic) NSInteger sum;
@property (nonatomic) NSInteger count;

@property (nonatomic) NSCountedSet *numberCounts; // must be initialized in `init`
@property (nonatomic) NSInteger mostFrequentNumber;

- (void)track:(NSInteger)number {
   if (self.count == 0) { 
      self.min = number;
      self.max = number;
      self.sum = number;
      self.count = 1;
      [self.numberCounts addObject:@(number)];
      self.mostFrequentNumber = number;
   } else {
      self.min = MIN(number, self.min);
      self.max = MAX(number, self.max);
      self.sum += number;
      self.count += 1;
      [self.numberCounts addObject:@(number)];
      if ([self.numberCounts countForObject:@(number)] > [self.numberCounts countForObject:@(self.mostFrequentNumber)] {
         self.mostFrequentNumber = number;
      }
   }
}

- (float)getMean {
   if (self.count == 0) { // protection against dividing by zero!
     return 0;
   }

   return ((float) self.sum) / self.count;
}

- (NSInteger)getMode {
   return self.mostFrequentNumber;
}

使用mode添加了NSCountedSet计算演示。 NSCountedSet可以使用其他语言的字典/地图进行模拟(我们必须在平均情况下使用具有O(1)运算的结构)。唯一的技巧是在添加时执行必要的操作。

另请注意,目前这些功能并不遵循Obj-C命名惯例,这在面试中也很重要。