iOS开发进阶-算法二

课程: 新浪微博资深大牛全方位剖析 iOS 高级面试

一、哈希算法

在一个字符串中找到第一个只出现一次的字符。例如:输入“abaccdeff”输出b。

思路:考察hash的使用,利用每个字母的ASCII码作hash来作为数组的index。使用一个数组存储每个字母出现的次数,数组记录的内容是该字母出现的次数,最终遍历字符串,找到第一个数组内容为1的字母即可。时间复杂度为O(n)。

char findFirstChar(char *cha) {
    char result = '\0';
    // 用于存放每个字符出现的次数,下标为字符的ASCII值
    int array[256] = {0};
    char *p = cha;
    // 遍历字符串,根据ASCII值存入数组中
    while (*p != '\0') {
        // 字符对应的存储位置,进行次数+1操作。
        array[*(p++)]++;
    }
    //重置p指针
    p = cha;
    while (*p != '\0') {
        // 遇到第一个出现次数为1的字符,打印出结果。
        if (array[*p] == 1) {
            result = *p;
            break;
        }
        p++;
    }
    return result;
}

测试代码:

void hash_findFirstCharTest() {
    char *cha = "gabaccdeff";
    char fc = findFirstChar(cha);
    printf("this char is %c \n", fc);
}

输出结果:
this char is g

二、 查找两个子视图的共同父视图

思路:记录视图A的所有父视图存放到数组A。将视图B的所有父视图存放到数组B。然后倒序比较两个数组中的视图,当比较到第一个不一样时,之前找到的就是所有共同父视图。

示例代码:

- (NSArray<NSView *> *)findCommonSuperView:(NSView *)view other:(NSView *)viewOther {
    // 结果数组
    NSMutableArray *result = [NSMutableArray array];
    // 两个子视图所有父视图组成的数组。
    NSArray *aSuperViews = [self findSuperView:view];
    NSArray *bSuperViews = [self findSuperView:viewOther];
    int i = 0;
    // 越界条件选取小的那个
    while (i < MIN(aSuperViews.count, bSuperViews.count)) {
        NSView *aSuperView = [aSuperViews objectAtIndex:aSuperViews.count - i - 1];
        NSView *bSuperView = [bSuperViews objectAtIndex:bSuperViews.count - i - 1];
        // 比较是否相等,相等则为共同父视图。不相等结束遍历。
        if (aSuperView == bSuperView) {
            [result addObject:aSuperView];
            i++;
        } else {
            break;
        }
    }
    return result;
}
- (NSArray <NSView *> *)findSuperView:(NSView *)view {
    // 第一个父视图
    NSView *temp = view.superview;
    NSMutableArray *result = [NSMutableArray array];
    while (temp) {
        [result addObject:temp];
        temp = temp.superview;
    }
    return result;
}

注意引入的是AppKit所以视图为NSView

三、无序数组中的中位数。

方案:排序算法 + 中位数;利用快排思路(分治思想)。
关于排序算法这里不再赘述,可以网上搜索。
中位数:当n为奇数时,(n + 1)/2 ;当n为偶数时,(n / 2 + (n / 2 + 1)/ 2。

思路:快排思想。任意选择一个元素,以该元素为支点划分数组为两部分,如果左侧集合长度恰好为(n -1)/2,那么支点就是中位数。如果左侧长度小于(n - 1)/2,那么中位数在右侧,否则中位数在左侧。

示例代码:

// 无序数组的中位数
int findMedian(int a[], int aLen) {
    
    int low = 0;
    int high = aLen - 1;
    
    // 中位下标
    int mid = (aLen - 1) / 2;
    // 第一遍快排
    int div = PartSort(a, low, high);
    
    while (div != mid) {
        if (mid < div) {
            // 左半区间
            div = PartSort(a, low, div - 1); // 递归
        } else {
            //右半区间
            div = PartSort(a, div + 1, high); // 递归
        }
    }
    return a[mid];
}

int PartSort(int a[], int start, int end) {
    // 两个哨兵
    int low = start;
    int high = end;
    // 关键数
    int key = a[end];
    while (low < high) {
        // 左边的值要比Key小
        while (low < high && a[low] <= key) {
            ++low;
        }
        // 右边的值要比Key大
        while (low < high && a[high] >= key) {
            --high;
        }
        // 交换两个哨兵对应的值
        if (low < high) {
            int temp = a[low];
            a[low] = a[high];
            a[high] = temp;
        }
    }
    // 交换关键数
    int temp = a[high];
    a[high] = a[end];
    a[end] = temp;
    return low;
}

测试代码:

void findMedianTest() {
    int list[9] = {12,3,10,8,6,7,11,13,9};
    // 3 6 7 8 9 10 11 12 13
    //         ^
    int median = findMedian(list, 9);
    printf("the median is %d \n", median);
}

输出结果:
the median is 9

小结

示例代码仓库地址:Algorithm

算法篇暂时告一段落,以上只是几个基本的算法题,仅仅是九牛一毛。推荐两个网站:leetCode牛客网

推荐阅读更多精彩内容

  • pdf下载地址:Java面试宝典 第一章内容介绍 20 第二章JavaSE基础 21 一、Java面向对象 21 ...
    王震阳阅读 77,558评论 25 510
  • 栈 1. 栈(stack)又名堆栈,它是一种运算受限的线性表。其限制是仅允许在表的一端进行插入和删除运算。这一端被...
    IT程序员阅读 3,019评论 0 8
  • 一进城,云缺他们就放弃了马车,改为步行。在南岭这样的小镇上,突然来了一辆豪华马车,那可算是惊天动地的大事了。 “我...
    楚冬阅读 24评论 0 0
  • 姓名:张爱玲 企业名称: 金柳工艺品有限公司 组别:第373期 利他1组 【日精进打卡第 50天】 经典名句 在...
    花半里_5ab7阅读 11评论 0 0
  • 又有很长一段时间没有写文章了。 上次写文章,还是参加林雨老师的写作班,被“逼”着写得,一个星期一篇,也不是很困难的...
    杨鉴韬阅读 38评论 0 1