我刚从一家公司接受了面试测试,我轻松地完成了它,但他们说我的功能在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)中完成此操作。我已经放弃了原因,所以不要认为你给我一个面试的答案。我不打算在那里工作。我只是想知道如何在不迭代数组的情况下解决这个问题。
答案 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命名惯例,这在面试中也很重要。