Objective c 如何在O(1)中完成此操作

Objective c 如何在O(1)中完成此操作,objective-c,big-o,little-o,Objective C,Big O,Little O,我刚从一家公司得到这个面试测试,我轻松地完成了它,但他们说我的功能处于o(n)状态。问题来了 使用以下方法编写一个类IntegerTracker: 确保每个方法(包括跟踪)在恒定时间内运行(O(1)时间复杂度) 我就是这样完成的 - (instancetype)init{ if(self == [super init]){ self.numbers = [[NSMutableArray alloc]init]; } return self; } - (v

我刚从一家公司得到这个面试测试,我轻松地完成了它,但他们说我的功能处于o(n)状态。问题来了

使用以下方法编写一个类IntegerTracker:

确保每个方法(包括跟踪)在恒定时间内运行(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;
}
-(instancetype)初始化{
if(self==[super init]){
self.numbers=[[NSMutableArray alloc]init];
}
回归自我;
}
-(void)trackInt:(int)编号{
[self.numbers addObject:[NSNumber numberwhithint:number]];
}
-(int)getMax{
NSNumber*max=[self.numbers valueForKeyPath:@“@max.self”];
返回[max intValue];
}
-(int)getMin{
NSNumber*min=[self.numbers valueForKeyPath:@“@min.self”];
返回[min intValue];
}
-(浮动)getMean{
NSNumber*average=[self.numbers valueForKeyPath:@“@avg.self”];
返回[平均浮动值];
}
-(int)getMode{
int maxCount=0;
int值=0;
NSMutableDictionary*模式=[[NSMutableDictionary alloc]init];
for(自编号中的NSNumber*n){
int currentCount=[[mode objectForKey:n.stringValue]intValue];
currentCount++;
[mode setObject:@(currentCount)forKey:n.stringValue];
如果(最大计数<当前计数){
maxCount=当前计数;
值=[n intValue];
}
}
返回值;
}

有人能告诉我应该如何在O(1)中完成这项工作吗。因为这个原因我已经不及格了,所以不要以为你会给我面试的答案。我不打算在那里工作。我只是想看看如何在不遍历数组的情况下解决这个问题。

我假设您必须以不同的方式编写
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; }
模式、平均值等的增量计算逻辑看起来有点不同,但您可能永远不必使用
数字
数组,但更可能的情况是要跟踪
计数
总和


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

使函数在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;
}
添加了使用
NSCountedSet
模式计算演示
NSCountedSet
可以使用其他语言中的字典/映射进行模拟(在一般情况下,我们必须使用带有O(1)操作的结构)。唯一的技巧是在添加时执行必要的操作


另外请注意,当前函数不遵循Obj-C命名约定,这在面试中也应该很重要。

每当调用
track
时,您可能必须重新计算最大值(以及其他值),如果新数字大于当前最大值,则更改最大值,否则不要更改最大值,等等。不,你不明白他们在问什么。他们希望我完成O(1)中的所有函数。在固定时间内。我不知道该怎么做。所有功能都需要在O(1)中完成。我在O(N)里做的。那么你怎么能在O(1)中完成它们呢?没有关系,但我不知道为什么你使用
stringValue
,而
n
(这是一个
NSNumber
)应该足以满足字典的
键。我必须在不到一个小时的时间内完成这项工作,而且它说我不能使用那里的NSNumber作为键。我知道我以前用过一个NSNUjmber作为密钥,但由于某种原因,它在OBJective C中给了我一个错误。这是一家公司为OBJective-C招聘人员,并分发了一个带有方法名称的规范,如
get_max()
?看起来你可能躲过了噩梦…@Esko918你在哪里挣扎?对于
min
你做的基本上是一样的,对于
avg
你存储它们的总和和计数,对于
mode
你可以存储一个字典,它以
number
作为键,数字出现的次数作为值。@Esko918我不想进一步争辩,我写的段落是O(1),没有迭代发生,只需按固定时间的键进行常规访问。对于平均值,您只需保持一个运行平均值和一个计数。第一首曲目发送一个数字。所以平均值是这个数字,计数是一。对于任何其他你做的((avg*count)+newInt)/(count+1)就是O(1)@Fogmeister,我个人不喜欢(avg*count)的想法,因为这有可能会失去精度-这取决于可能需要的要求(如果sum>intMaxValue)。@chux我不确定,但通常字典访问O(1)iirc,除非你们遇到最坏的情况,它将是O(n)。无论如何,没有要求它不能有一个包含40亿条目的表(或者不管您希望有多少条)。我不认为有一种方法永远是O(1),即使在最坏的情况下也是如此。请注意,该要求甚至没有说明时间复杂度是最佳、最差还是平均情况。那么您将如何获得该模式,但我可以用任何语言来实现这一点。那么,一种没有NSCountedSet的语言呢。我选择Objective-C是因为那是我申请的职位for@Esko918关于
NSCountedSet
我错了。我想这不会有什么帮助的。还有,这算什么?如果我给你数字1,4,3,1,1,5,4你怎么计算
@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;
}