-
Notifications
You must be signed in to change notification settings - Fork 3.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
查找两个view最近公共祖先那段逻辑算法复杂度是O(n²),可以优化 #578
Comments
有想法是好的,你可以把你的优化方案写出来,验证一下不就ok了吗 |
这样? - (__kindof MAS_VIEW *)mas_closestCommonSuperview:(MAS_VIEW *)view {
MAS_VIEW *closestCommonSuperview = self;
MAS_VIEW *secondViewSuperview = view;
while (closestCommonSuperview != secondViewSuperview) {
closestCommonSuperview = closestCommonSuperview == nil ? view : closestCommonSuperview.superview;
secondViewSuperview = secondViewSuperview == nil ? self : secondViewSuperview.superview;
}
return closestCommonSuperview;
} |
这么写感觉在某些case会陷入死循环,如果self的superview是nil,view也是nil的情况 |
返回 nil。 |
我给一个写法~ 但可能没有那么优雅: MAS_VIEW *firstView = self;
|
刚又分析了下 看了下 这样确实可以返回正确的结果 |
楼上都搞的太复杂了,只需要几个简单的if-else就可以优化95%的遍历次数。 优化代码如下: #pragma mark - heirachy
- (instancetype)mas_closestCommonSuperview:(MAS_VIEW *)view {
MAS_VIEW *closestCommonSuperview = nil;
// 一般约束关联的两个view要么是父子关系,要么是兄弟关系,碰运气可以大大优化链表遍历的时间
closestCommonSuperview = [self take_a_chance:view];
if (closestCommonSuperview)
return closestCommonSuperview;
MAS_VIEW *secondViewSuperview = view;
while (!closestCommonSuperview && secondViewSuperview) {
MAS_VIEW *firstViewSuperview = self;
while (!closestCommonSuperview && firstViewSuperview) {
if (secondViewSuperview == firstViewSuperview) {
closestCommonSuperview = secondViewSuperview;
}
firstViewSuperview = firstViewSuperview.superview;
}
secondViewSuperview = secondViewSuperview.superview;
}
return closestCommonSuperview;
}
/// 碰运气 快速找到common super view
- (MAS_VIEW *)take_a_chance:(MAS_VIEW *)secondView {
if (!secondView) return nil;
if (self == secondView) return self;
if (secondView.superview == self.superview && self.superview) {
return self.superview; // 兄弟关系
} else if (self.superview == secondView) {
return self.superview; // first 是 second 的子view
} else if (self == secondView.superview) {
return secondView.superview; // first 是 second 的父view
}
return nil;
} 优化结果如下:(某日活百万app启动,到首页不再layout) 优化前: 优化后: |
LGTM,搬走抄到我的 Fork 里 |
New Issue Checklist
Issue Info
如下代码:
(instancetype)mas_closestCommonSuperview:(MAS_VIEW *)view {
MAS_VIEW *closestCommonSuperview = nil;
MAS_VIEW *secondViewSuperview = view;
while (!closestCommonSuperview && secondViewSuperview) {
MAS_VIEW *firstViewSuperview = self;
while (!closestCommonSuperview && firstViewSuperview) {
if (secondViewSuperview == firstViewSuperview) {
closestCommonSuperview = secondViewSuperview;
}
firstViewSuperview = firstViewSuperview.superview;
}
secondViewSuperview = secondViewSuperview.superview;
}
return closestCommonSuperview;
}
上述代码意图为寻找两个View最近的公共父View,时间复杂度是O(n²),其实可以优化成O(n)。
将两个view作为两个链表的头结点,最顶层的superview作为尾结点,这样问题就转化为寻找两个链表的第一个相交节点的问题,从而变为一个复杂度为O(n)的问题。不知道这么考虑是否是正确的?
Issue Description
The text was updated successfully, but these errors were encountered: