iOS 面试题(一):寻找最近公共 View --转自唐巧
题目:找出两个 UIView 的最近的公共 View,如果不存在,则输出 nil 。
分析:这其实是数据结构里面的找最近公共祖先的问题。
一个 UIViewController
中的所有 view 之间的关系其实可以看成一颗树,UIViewController
的 view 变量是这颗树的根节点,其它的 view 都是根节点的直接或间接子节点。
所以我们可以通过 view 的 superview 属性,一直找到根节点。需要注意的是,在代码中,我们还需要考虑各种非法输入,如果输入了 nil,则也需要处理,避免异常。以下是找到指定 view 到根 view 的路径代码:
+ (NSArray *)superViews:(UIView *)view {
if (view == nil) {
return @[];
}
NSMutableArray *result = [NSMutableArray array];
while (view != nil) {
[result addObject:view];
view = view.superview;
}
return [result copy];
}
然后对于两个 view A 和 view B,我们可以得到两个路径,而本题中我们要找的是这里面最近的一个公共节点。
一个简单直接的办法:拿第一个路径中的所有节点,去第二个节点中查找。假设路径的平均长度是 N,因为每个节点都要找 N 次,一共有 N 个节点,所以这个办法的时间复杂度是 O(N^2)。
+ (UIView *)commonView_1:(UIView *)viewA andView:(UIView *)viewB {
NSArray *arr1 = [self superViews:viewA];
NSArray *arr2 = [self superViews:viewB];
for (NSUInteger i = ; i < arr1.count; ++i) {
UIView *targetView = arr1[i];
for (NSUInteger j = ; j < arr2.count; ++j) {
if (targetView == arr2[j]) {
return targetView;
}
}
}
return nil;
}
一个改进的办法:我们将一个路径中的所有点先放进 NSSet 中。因为 NSSet 的内部实现是一个 hash 表,所以查找元素的时间复杂度变成了 O(1),我们一共有 N 个节点,所以总时间复杂度优化到了 O(N)。
+ (UIView *)commonView_2:(UIView *)viewA andView:(UIView *)viewB {
NSArray *arr1 = [self superViews:viewA];
NSArray *arr2 = [self superViews:viewB];
NSSet *set = [NSSet setWithArray:arr2];
for (NSUInteger i = ; i < arr1.count; ++i) {
UIView *targetView = arr1[i];
if ([set containsObject:targetView]) {
return targetView;
}
}
return nil;
}
除了使用 NSSet 外,我们还可以使用类似归并排序的思想,用两个「指针」,分别指向两个路径的根节点,然后从根节点开始,找第一个不同的节点,第一个不同节点的上一个公共节点,就是我们的答案。代码如下:
/* O(N) Solution */
+ (UIView *)commonView_3:(UIView *)viewA andView:(UIView *)viewB {
NSArray *arr1 = [self superViews:viewA];
NSArray *arr2 = [self superViews:viewB];
NSInteger p1 = arr1.count - ;
NSInteger p2 = arr2.count - ;
UIView *answer = nil;
while (p1 >= && p2 >= ) {
if (arr1[p1] == arr2[p2]) {
answer = arr1[p1];
}
p1--;
p2--;
}
return answer;
}
我们还可以使用 UIView 的 isDescendant 方法来简化我们的代码,不过这样写的话,时间复杂度应该也是 O(N^2) 的。lexrus 提供了如下的 Swift 版本的代码:
/// without flatMap
extension UIView {
func commonSuperview(of view: UIView) -> UIView? {
if let s = superview {
if view.isDescendant(of: s) {
return s
} else {
return s.commonSuperview(of: view)
}
}
return nil
}
}
特别地,如果我们利用 Optinal 的 flatMap 方法,可以将上面的代码简化得更短,基本上算是一行代码搞定。怎么样,你学会了吗?
extension UIView {
func commonSuperview(of view: UIView) -> UIView? {
return superview.flatMap {
view.isDescendant(of: $) ?
$ : $.commonSuperview(of: view)
}
}
}
iOS 面试题(一):寻找最近公共 View --转自唐巧的更多相关文章
- iOS开发寻找最近公共view
新技能 #pragma mark --寻找最近公共view + (NSArray *)superViews:(UIView *)view{ if (view==nil) { return @[]; } ...
- iOS之面试题:腾讯三次面试以及参考思路
使用了第三方库, 有看他们是怎么实现的吗? 例:SD.YY.AFN.MJ等! <1>.SD为例: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ...
- 大厂常问iOS面试题--性能优化篇
1.造成tableView卡顿的原因有哪些? 1.最常用的就是cell的重用, 注册重用标识符 如果不重用cell时,每当一个cell显示到屏幕上时,就会重新创建一个新的cell 如果有很多数据的时候 ...
- 最全的iOS面试题及答案-转载
1. Object-c的类可以多重继承么?可以实现多个接口么?Category是什么?重写一个类的方式用继承好还是分类好?为什么? 答: Object-c的类不可以多重继承:可以实现多个接口,通过实现 ...
- iOS面试题及答案2015.6.7
iOS面试题及答案 1. Object-c的类可以多重继承么?可以实现多个接口么?Category是什么?重写一个类的方式用继承好还是分类好?为什么? 答: Object-c的类不可以多重继承 ...
- [转载]iOS面试题总
转载自:http://blog.sina.com.cn/s/blog_67eb608b0101r6xb.html (2014-06-13 20:23:33) 转载▼ 标签: 转载 crash 原文 ...
- 试答卓同学的 iOS 面试题
卓同学昨天写了一篇文章<4道过滤菜鸟的iOS面试题>.我手痒决定默写一个参考答案.后来发现不认真回答被大家喷成狗,所以决定积极改造,重新做人.下面就是修编之后的答案. 1. struct和 ...
- iOS面试题大全-点亮你iOS技能树
所有的内容大部分来自于网络的搜集,所以我不是一个创造者,而是一个搬运工.我尽量把题目,尤其是参考答案的出处列明.若有任何疑问,建议,意见,请联系我. 第一部分面试题来源于iOS-Developer-I ...
- 原 iOS面试题收集
原 iOS面试题收集 发表于2年前(2013-07-22 13:47) 阅读(369) | 评论(0) 4人收藏此文章, 我要收藏 赞0 听云性能监测产品App.Server.CDN免费试用,绑定 ...
随机推荐
- 在shell 上执行mongo 查询
需求 在写小工具的时候,经常遇到需要从mongodb 里面查东西来用,因为要跟其他bash 工具链结合在一起用,所以最理想的方法是能够在shell 上执行查询,然后pipe 给接下来的工具做处理. 方 ...
- [BI项目记]-搭建代码管理环境之云端
这一篇主要介绍云端的TFS.微软在云端解决方案为我们提供了不错的选择,当本地的资源无法满足部署一个TFS的环境的时候,在互联网连接允许的情况下,可以考虑使用Visual Studio Online. ...
- 【leetcode】Remove Element
题目概述: Given an array and a value, remove all instances of that value in place and return the new len ...
- Asp.net中导出Excel文档(Gridview)
主要思路,通过GridView来导出文档. 新建一个Aspx页面,页面创建GridView控件,后台绑定好数据源.然后load中直接打印即可导出 前台的GridView <asp:GridVie ...
- github之git基本命令介绍的简单整理
git 格式: git [--version] [--exec-path[=<path>]] [--html-path] [--info-path] [-p|--paginate|--no ...
- Codeforces Round #370 - #379 (Div. 2)
题意: 思路: Codeforces Round #370(Solved: 4 out of 5) A - Memory and Crow 题意:有一个序列,然后对每一个进行ai = bi - bi ...
- javascript将object转string字符串
var jsonData = {a:1,b:2}; function obj2string(o) { var r = []; if (typeof o == "string") { ...
- iOS--NSBundle理解
NSBundle:官方文档解释:An NSBundle object represents a location in the file system that groups code and r ...
- 防止 jsp被sql注入的五种方法
一.SQL注入简介 SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,而是针对程序员编程时的疏忽,通过SQL语句,实现无帐号登录,甚至篡改数据库. 二.SQL注入攻击的总体 ...
- Java-Android【1】-控制手机震动
一.配置震动授权 1.在AndroidManifest.xml文件中添加<manifest></manifest>中添加一行 <uses-permission andro ...