iOS 头条面试

今天参加了头条的高级 iOS 岗位面试,1.5 h,一共两道题。一道问答,另外一道是算法。算法要求必须在纸上写出完整的代码,否则就算 Fail 。对于 iOS 开发者来说,除非处于研究目的,链表使用的场景真的不多。只能依据仅存在记忆中的大学 C 语言知识,边回忆变应用于眼前的算法题。最后结果完全在预料之中--「落榜」。

利用闲余时间,详细整理了一下问题和答案,供后来人准备。
问题1:iOS 消息调用过程;
问题2 :然后就拿出了一个链表的题目,要求手写算法:

两个链表 L1、 L2, 存储的是 10 以内的整数,求两个链表各个元素相加的结果。比如 L1 = 1 -> 2 -> 3 -> 5->9; L2 = 2 -> 1 -> 4 -> 7->1; 然后结果 res = 3->3->8->4->0.

答案 1 :iOS 消息调用属于基本知识,苹果官方有一个详细的介绍图:


image.png

iOS 工程中,调用对象的方法,就是向对象发送消息。我们知道,iOS 中的方法分为实例方法和对象方法。iOS 所有的对象都是继承至 NSObject, 编译完成后,在对象的定义中,存在一个实例方法链表、一个缓存方法链表。当对实例 son 发送消息后,会在 son 缓存方法链表中寻找;缓存中没有时,向实例方法链表寻找;再找不到,会向父类的实例方法缓存链表 -> 父类的实例方法链表寻找,直至 NSObject。在 NSObject 中会经历以下两个步骤:

1 - (BOOL)resolveInstanceMethod:(SEL)sel ; 
2 - (id)forwardingTargetForSelector:(SEL)aSelector ;

如果在步骤 2 中范围 nil, 就会触发 iOS 的崩溃。
当向 Son 发送类方法时,会首先向 Son 的元类 metaClass 中的类缓存方法链表中寻找,然后类方法链表,然后直接在 NSObject 进行缓存方法链表 -> 类方法链表的寻找路径 . 在 NSObject 中会经历如下两个步骤:

实例的 methodList 链表中寻找方法,找不到时会寻找 Son 的类方法,仍然找不到时,会寻找父类的方法链表,直到 NSObject 。

其中不同对象间的切换,通过 isa 指针完成,实例 son 的 isa 指向类 Son, 类 Son 的 isa 指向元类,元类的 isa 指向父类的元类, 父类的元类向上传递,直至 NSObject .

NSObject 的指针 isa 指向其本身,在想 NSObject 发送消息时,会经历如下步骤:

1 + (BOOL)resolveClassMethod:(SEL)sel ; 
2 - (void)doesNotRecognizeSelector:(SEL)aSelector ;

当调用方法 2 时,会触发 iOS 的崩溃。利用以上机制,可以对resolveInstanceMethod 和 resolveClassMethod 两个方法进行方法交换,拦截可能出现的 iOS 崩溃,然后自定义处理。

如果理解了以上机制,就能明白这个题目

答案 2 首先讲解一下实现思路:计算链表和,需要从后往前计算,进位需要保存,用于下一个链表和。最后一个链表计算后,如果还存在进位,需要新建节点保存结果。

题目中链表属于单向,只能从前往后遍历,所以首先需要将链表反向,然后对结果采用头插法的方式进行保存。下面直接上代码:

- (void)jiSuanHe{
    ListNode *l1_1 = malloc(sizeof(ListNode));
    l1_1->value = 9;
    ListNode *l1_2 = malloc(sizeof(ListNode));
    l1_2->value = 8;
    l1_1->next = l1_2;
    ListNode *l1_3 = malloc(sizeof(ListNode));
    l1_3->value = 7;
    l1_2->next = l1_3;
    ListNode *l1_4 = malloc(sizeof(ListNode));
    l1_4->value = 5;
    l1_3->next = l1_4;
    ListNode *l1_5 = malloc(sizeof(ListNode));
    l1_5->value = 3;
    l1_5->next = NULL;
    l1_4->next = l1_5;
    
    ListNode *l2_1 = malloc(sizeof(ListNode));
    l2_1->value = 9;
    ListNode *l2_2 = malloc(sizeof(ListNode));
    l2_2->value = 8;
    l2_1->next = l1_2;
    ListNode *l2_3 = malloc(sizeof(ListNode));
    l2_3->value = 7;
    l2_2->next = l1_3;
    ListNode *l2_4 = malloc(sizeof(ListNode));
    l2_4->value = 5;
    l2_3->next = l1_4;
    //    ListNode *l2_5 = malloc(sizeof(ListNode));
    //    l2_5->value = 3;
    //    l2_5->next = NULL;
    //    l2_4->next = l1_5;
    
    ListNode *l1 = l1_1;
    ListNode *l2 = l2_1;
    
    printf("\n****\n");
    ListNode *l1_reverse = [self reverseList:l1];
    ListNode *l2_reverse = [self reverseList:l2];
    printf("\n--l1---\n");
    [self printList:l1_reverse];
    printf("\n--l2---\n");
    [self printList:l2_reverse];
    
    ListNode *temp1 = l1_reverse;
    ListNode *temp2 = l2_reverse;
    int jinWei = 0;
    int i = 0;
    ListNode *res;
    while (temp1 != NULL || temp2 != NULL) {
        int value1 = 0, value2 = 0;
        if (temp1 != NULL) {
            value1 = temp1 -> value;
        }
        if (temp2 != NULL) {
            value2 = temp2 -> value;
        }
        int yu = (value1 + value1 + jinWei) % 10;
        jinWei = (value1 + value1 + jinWei) / 10;
        ListNode *tempRes = malloc(sizeof(ListNode));
        tempRes -> value = yu;
        if (i == 0) {
            tempRes -> next = NULL;
        }else{
            tempRes -> next = res;
        }
        res = tempRes;
        temp1 = temp1 -> next;
        temp2 = temp2 -> next;
        i++;
    }
    
    if (jinWei != 0) {
        ListNode *tempRes = malloc(sizeof(ListNode));
        tempRes -> value = jinWei;
        tempRes -> next = res;
        res = tempRes;
    }
    
    printf("\n***结果\n");
    [self printList:res];
    printf("\n");
}

- (ListNode *)reverseList:(ListNode *)listNode{
    ListNode *resL;
    ListNode *l = listNode;
    int i = 0;
    while (l != NULL) {
        ListNode *temp = malloc(sizeof(ListNode));
        temp -> value = l -> value;
        if (i==0) {
            temp->next = NULL;
        }else{
            temp->next = resL;
        }
        resL = temp;
        i++;
        l = l -> next;
    }
    return resL;
}

- (void)printList:(ListNode *)listNode{
    ListNode *node = listNode;
    while (node != NULL) {
        printf("value = %d ", node->value);
        node = node->next;
    }
}

算法题目并不算难,但是想要在面试期间的短时间内顺利解决,则需要平常不断的积累。算法意识是一个程序员进阶必须经过的磨炼,从这个角度,进入头条的人都具备了成长的潜力。当然,作为雇主的头条大概率上也会越来越好。虽然这次失败了,但是对头条的印象却好起来了,希望以后还有尝试的机会,加油~

喜欢和关注都是对我的鼓励和支持~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容