- (NSArray *)superCalsses:(UIView *)class{
if (!class) {
return @[];
}
NSMutableArray * result = [NSMutableArray array];
while (class) {
[result addObject:class];
class = [class superview];
}
return [result copy];
}
/**
*基于两个view的父视图链条长度来判断 时间复杂度O(N) 空间复杂度O(1)
**/
- (UIView *)commonClass1:(UIView *)classA andClass:(UIView *)classB{
NSArray* arr1 = [self superCalsses:classA];
NSArray* arr2 = [self superCalsses:classB];
NSInteger count = arr1.count < arr2.count ? arr1.count : arr2.count;
UIView * resultClass;
for (int i = 0; i < count; ++i) {
UIView * clA = arr1[arr1.count - i - 1];
UIView * clB = arr2[arr2.count - i - 1];
if (clA == clB) {
resultClass = clA;
}else{
break;
}
}
return resultClass;
}
/**
* 我们将一个路径中的所有点先放进 NSSet 中。因为 NSSet 的内部实现是一个 hash 表,所以查找元素的时间复杂度变成了 O(1),我们一共有 N 个节点,所以总时间复杂度优化到了 O(N)。
*
**/
- (UIView *)commonClass1_V2:(UIView *)classA andClass:(UIView *)classB{
NSArray* arr1 = [self superCalsses:classA];
NSArray* arr2 = [self superCalsses:classB];
NSSet *set = [NSSet setWithArray:arr2];
for (int i = 0; i < arr1.count; ++i) {
UIView *targetView = arr1[i];
if ([set containsObject:targetView]) {
return targetView;
}
}
return nil;
}
/**
* 除了使用 NSSet 外,我们还可以使用类似归并排序的思想,用两个「指针」,分别指向两个路径的根节点,然后从根节点开始,找第一个不同的节点,第一个不同节点的上一个公共节点,就是我们的答案。
* O(N)
*/
- (UIView *)commonClass1_V3:(UIView *)classA andClass:(UIView *)classB{
NSArray* arr1 = [self superCalsses:classA];
NSArray* arr2 = [self superCalsses:classB];
NSInteger p1 = arr1.count - 1;
NSInteger p2 = arr2.count - 1;
UIView *answer = nil;
while (p1 >=0 && p2 >= 0) {
if (arr1[p1] == arr2[p2]) {
answer = arr1[p1];
}
p1--;
p2--;
}
return answer;
}