题目:找出两个 UIView 的最近的公共 View,如果不存在,则输出 nil 。

- (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;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个示例代码,可以创建一个可缩放的 UIView,并确保它的尺寸不会小于视图: 在 .h 文件中声明 UIPinchGestureRecognizer 和一个指向视图的 UIView 属性: ``` #import <UIKit/UIKit.h> @interface ViewController : UIViewController @property (nonatomic, strong) UIPinchGestureRecognizer *pinchGesture; @property (nonatomic, strong) UIView *parentView; @end ``` 在 .m 文件中实现 UIPinchGestureRecognizer 和 UIView 的创建和缩放逻辑: ``` #import "ViewController.h" @interface ViewController () @property (nonatomic, strong) UIView *resizableView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // 创建视图 self.parentView = [[UIView alloc] initWithFrame:self.view.bounds]; self.parentView.backgroundColor = [UIColor lightGrayColor]; [self.view addSubview:self.parentView]; // 创建可缩放的视图 self.resizableView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; self.resizableView.backgroundColor = [UIColor redColor]; [self.parentView addSubview:self.resizableView]; // 创建缩放手势识别器 self.pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinchGesture:)]; [self.resizableView addGestureRecognizer:self.pinchGesture]; } - (void)handlePinchGesture:(UIPinchGestureRecognizer *)gestureRecognizer { if (gestureRecognizer.state == UIGestureRecognizerStateChanged) { // 计算缩放比例 CGFloat scale = gestureRecognizer.scale; // 计算缩放后的视图大小 CGSize newSize = CGSizeMake(self.resizableView.frame.size.width * scale, self.resizableView.frame.size.height * scale); // 判断缩放后的大小是否小于视图的大小 if (newSize.width >= self.parentView.frame.size.width && newSize.height >= self.parentView.frame.size.height) { // 缩放视图 self.resizableView.transform = CGAffineTransformScale(self.resizableView.transform, scale, scale); // 重置手势识别器的缩放比例 gestureRecognizer.scale = 1.0; } } } @end ``` 在这个示例中,创建了一个视图 self.parentView 和一个可缩放的子视图 self.resizableView,并将子视图添加到视图中。然后创建了一个 UIPinchGestureRecognizer 对象 self.pinchGesture,并将它添加到子视图中。 在 handlePinchGesture: 方法中,计算出缩放比例和缩放后的视图大小,并判断缩放后的大小是否小于视图的大小。如果缩放后的大小不小于视图的大小,就缩放视图,并重置手势识别器的缩放比例。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值