iOS面試‘騰訊阿里網(wǎng)易’上來(lái)就四道算法題?(一)

前言

現(xiàn)在出去面, 如果是面中高級(jí)的, 基本不會(huì)問(wèn)那些特別基礎(chǔ)的東西了, 底層這塊問(wèn)到的是最多的,現(xiàn)在大廠有一點(diǎn),你在一個(gè)項(xiàng)目組面完了, 基礎(chǔ)面試這一塊就不用在面了! 特別在乎的是做過(guò)的項(xiàng)目. 如果項(xiàng)目好久很好說(shuō)話, 項(xiàng)目不好很被動(dòng), 不知道怎么去補(bǔ)。

面試的開(kāi)始還是算法+底層

由于我面試的都是比較大的公司,所以自然也是做了這方面的準(zhǔn)備,現(xiàn)在面試iOS中高級(jí)開(kāi)發(fā),算法題已是必然會(huì)出現(xiàn)的一個(gè)環(huán)節(jié)了,這里把面試遇到的算法題和LeetCode上一些比較經(jīng)典的算法題做一個(gè)匯總,希望對(duì)大家有用。

持續(xù)更新--請(qǐng)iOS的小伙伴關(guān)注! 喜歡的話給一個(gè)贊吧!

題目

  • 1 實(shí)現(xiàn)一個(gè)方法,計(jì)算100的階乘。
  • 2 編程實(shí)現(xiàn)字符串拷貝,要考慮下內(nèi)存重疊問(wèn)題。
  • 3 對(duì)輸入的字符串,去除其中的字符‘b’以及連續(xù)出現(xiàn)的‘a(chǎn)’和‘c
  • 4 如何求兩個(gè)View的最近公共父類

1 實(shí)現(xiàn)一個(gè)方法,計(jì)算100的階乘。

主要考慮到通用性,還有就是盡量不要使用遞歸,會(huì)導(dǎo)致方法??臻g占用過(guò)大。所以采用for循環(huán)的方式進(jìn)行計(jì)算就OK。

#import <Foundation/Foundation.h>

long long dofactorial(int min, int max){
    if(min > max){
        return 0;
    }
    if(min == 0){
        if(max == 0){
            //0的階乘是1
            return 1;
        }else{
            min = 1;
        }
        
    }
    long long result = 1;
    for (int i = min; i <= max; i++) {
        result *= i;
     
        if(result > INT_MAX){
            //考慮溢出
            return -1;
        }
    }
    return result;
}

int main(int argc, const char * argv[]) {
    
    int result = dofactorial(0, 100);
    printf("result = %lld", result);

    return 0;
}

2 編程實(shí)現(xiàn)字符串拷貝,要考慮下內(nèi)存重疊問(wèn)題。

解決思路:既然要考慮內(nèi)存重疊的問(wèn)題,就是說(shuō)可能目標(biāo)地址的起始位置是在源字符串的后半段,或者目標(biāo)的結(jié)束位置在源字符串的前半段。第一種情況,從末尾開(kāi)始復(fù)制可以解決問(wèn)題,同理:第二種情況,從首位開(kāi)始復(fù)制可以解決問(wèn)題,代碼如下:

char *memcpy_qi(char *dst, const char* src, int cl)
{
    assert(dst != NULL && src != NULL);
    char *ret = dst;
    if (dst >= src && dst <= src+ cl-1) //內(nèi)存重疊,從高地址開(kāi)始復(fù)制
    {
        //挪開(kāi)空間
        dst = dst+ cl-1;
        //將指針挪到結(jié)尾
        src = src+ cl-1;
        while (cl—)
            *dst— = *src—;
    }
    else    //正常情況,從低地址開(kāi)始復(fù)制
    {
        while (cl—)
            *dst++ = *src++;
    }
    
    return ret;
}
char * strcpy_qi(char *dst,const char *src)
{
    assert(dst != NULL && src != NULL);
    char *ret = dst;
    memcpy_qi(dst, src, strlen(src)+1);
    return ret;
}

3. 對(duì)輸入的字符串,去除其中的字符‘b’以及連續(xù)出現(xiàn)的‘a(chǎn)’和‘c’

樣例:
‘a(chǎn)acbd’ -> 'ad'
'aabcd' -> 'ad'
'aaabbccc' -> ''
不允許使用類似string.replace函數(shù)
要求時(shí)間、空間復(fù)雜度盡量?jī)?yōu)化

4 如何求兩個(gè)View的最近公共父類

解決思路:
首先,這個(gè)問(wèn)題必然不能按照常規(guī)的方式去對(duì)一個(gè)VIew的所有父類去進(jìn)行for循環(huán)比較,那這個(gè)題出的就沒(méi)有意義。
再,每個(gè)類的所有父類組成了一個(gè)繼承鏈,而在UIKit下,所有的UIView的最終父類也必然是NSObject,其實(shí)就相當(dāng)于這兩個(gè)類的繼承鏈從NSObject開(kāi)始向下一直是重合的,直到最后的一個(gè)公共父類才開(kāi)始分開(kāi),這個(gè)最后的公共父類也是最近的公共父類,這是典型的倒Y字型鏈表組合。那么解題思路就很好做了,具體代碼如下:

- (void)viewDidLoad {
    [super viewDidLoad];
    Class commonClass = [self commonClass1:[ViewA class] andClass:[ViewB class]];
    NSLog(@"最近公共父類為:%@",commonClass);
}
// 獲取所有父類
- (NSArray *)superClasses:(Class)class {
    if (class == nil) {
        return @[];
    }
    NSMutableArray *result = [NSMutableArray array];
    while (class != nil) {
        [result addObject:class];
        class = [class superclass];
    }
    return [result copy];
}
//對(duì)兩條鏈表進(jìn)行比對(duì)
- (Class)commonClass1:(Class)classA andClass:(Class)classB {
    NSArray *arr1 = [self superClasses:classA];
    NSArray *arr2 = [self superClasses:classB];
    NSInteger count = arr1.count < arr2.count ? arr1.count : arr2.count;
    Class resultClass;
    for (NSUInteger i = 0; i < arr1.count; ++i) {
        Class classA = arr1[arr1.count - i - 1];
        Class classB = arr2[arr2.count - i - 1];
        if(classA == classB){
            resultClass = classA;
        }else{
            break;
        }
    }
    return resultClass;
}

4.如何用兩個(gè)骰子表示一個(gè)月的完整日期

分享個(gè)以前朋友給我出的問(wèn)題,問(wèn)題是這樣的:現(xiàn)有兩個(gè)骰子,每個(gè)骰子6個(gè)面,全是空的,現(xiàn)在需要用這兩個(gè)骰子表示年月日中的日的全部情況(1-31),1號(hào)算01,一個(gè)骰子只能表示一位,且不能兩位都用同一個(gè)骰子,那么在這種情況下,每個(gè)骰子的六個(gè)面上該怎么刻數(shù)字呢?
解決思路:
一、月份的日期,是從1號(hào)到31號(hào)的,那十位上的所有可能性就是0、1、2、3.個(gè)位上也是包含這幾個(gè)數(shù)的,那么0、1、2、3必然兩個(gè)骰子上都有。
二、但是,十位為3的情況只有30,31,在兩個(gè)骰子上都有0、1、2的情況下,3只在一個(gè)骰子有也可以表示出來(lái)的,顛倒位置即可,那么就是0、1、2必須每個(gè)骰子上都有。
三、兩頭骰子此時(shí)還剩下6個(gè)面,日期必須的數(shù)字此時(shí)還剩下,3、4、5、6、7、8、9一共7個(gè)數(shù),數(shù)字比面數(shù)多一個(gè),那就是還得想辦法再節(jié)省一個(gè)。這個(gè)時(shí)候就要考慮下6和9能不用共用一個(gè)面了。
答案:
骰子A : 0、1、2、3、4、5
骰子B : 0、1、2、6、7、8

文章題目已經(jīng)整理為完整的答案文檔!需要的話可以添加QQiOS交流群:761407670 進(jìn)群密碼000,不管你是小白還是大牛歡迎入駐 ,分享BAT,阿里面試題、面試經(jīng)驗(yàn),討論技術(shù), 大家一起交流學(xué)習(xí)成長(zhǎng)!

另附上一份各收集的大廠面試題,進(jìn)群可自行下載!

底層面試題

記不太清了23333.....底層是問(wèn)最多的就是runtime,項(xiàng)目這塊問(wèn)題需要充足準(zhǔn)備?。?!

1.runtime相關(guān)問(wèn)題

一個(gè)objc對(duì)象的isa的指針指向什么?有什么作用?

說(shuō)一下對(duì) isa 指針的理解, 對(duì)象的isa 指針指向哪里?isa 指針有哪兩種類型?

使用runtime Associate方法關(guān)聯(lián)的對(duì)象,需要在主對(duì)象dealloc的時(shí)候釋放么?

2.Block

Block如何變量截獲?
Block的幾種形式?

3.性能優(yōu)化

如何高性能的畫(huà)一個(gè)圓角?
什么是 離屏渲染?什么情況下會(huì)觸發(fā)?該如何應(yīng)對(duì)?
如何提升 tableview 的流暢度?

4.Runloop

為什么 NSTimer 有時(shí)候不好使?

AFNetworking 中如何運(yùn)用 Runloop?

PerformSelector:afterDelay:這個(gè)方法在子線程中是否起作用?為什么?怎么解決?

5.什么是函數(shù)式編程?

函數(shù)可以接受函數(shù)當(dāng)作輸入(參數(shù))和輸出(返回值)。

6.什么是ABI?

應(yīng)用程序二進(jìn)制接口(application binary interface,ABI) 描述了應(yīng)用程序和操作系統(tǒng)之間,一個(gè)應(yīng)用和它的庫(kù)之間,或者應(yīng)用的組成部分之間的低接口 。ABI不同于API ,API定義了源代碼和庫(kù)之間的接口,因此同樣的代碼可以在支持這個(gè)API的任何系統(tǒng)中編譯

7.什么是MVC,請(qǐng)結(jié)合CocoaTouch說(shuō)明?

8.什么是MVVM,請(qǐng)?jiān)O(shè)計(jì)View moled需要考慮哪些?

    1. 低耦合。視圖(View)可以獨(dú)立于Model變化和修改,一個(gè)ViewModel可以綁定到不同的"View"上,當(dāng)View變化的時(shí)候Model不可以不變,當(dāng)Model變化的時(shí)候View也可以不變。
    1. 可重用性。你可以把一些視圖邏輯放在一個(gè)ViewModel里面,讓很多view重用這段視圖邏輯。
    1. 獨(dú)立開(kāi)發(fā)。開(kāi)發(fā)人員可以專注于業(yè)務(wù)邏輯和數(shù)據(jù)的開(kāi)發(fā)(ViewModel),設(shè)計(jì)人員可以專注于頁(yè)面設(shè)計(jì),使用Expression Blend可以很容易設(shè)計(jì)界面并生成xaml代碼。
    1. 可測(cè)試。界面素來(lái)是比較難于測(cè)試的,而現(xiàn)在測(cè)試可以針對(duì)ViewModel來(lái)寫(xiě)。

9.swift相對(duì)于OC有哪些優(yōu)點(diǎn)?

簡(jiǎn)潔的語(yǔ)法:
我們不得不承認(rèn)的是swift語(yǔ)言比OC精簡(jiǎn),整個(gè)項(xiàng)目中丟掉了頭文件,以及頭文件的引入。

報(bào)錯(cuò)精準(zhǔn):
報(bào)錯(cuò)的時(shí)候直接顯示報(bào)錯(cuò)行。

定義變量簡(jiǎn)單:
定義變量不用區(qū)分整型,浮點(diǎn)型等等,變量使用var,常量使用let。

可視化互動(dòng)效果:
開(kāi)發(fā)工具帶來(lái)了Xcode Playgrounds功能,該功能提供強(qiáng)大的互動(dòng)效果,能讓Swift源代碼在撰寫(xiě)過(guò)程中實(shí)時(shí)顯示出其運(yùn)行結(jié)果。

函數(shù)式編程的支持:
Swift 語(yǔ)言本身提供了對(duì)函數(shù)式編程的支持;

Objc 本身是不支持的,通過(guò)引入 ReactiveCocoa 這個(gè)庫(kù)才可支持函數(shù)式編程。

持續(xù)更新--請(qǐng)iOS的小伙伴關(guān)注! 喜歡的話給一個(gè)贊吧!

該偏文章所有題目已經(jīng)整理為完整的答案文檔!需要的話可以添加QQiOS交流群:761407670 進(jìn)群密碼000,不管你是小白還是大牛歡迎入駐 ,分享BAT,阿里面試題、面試經(jīng)驗(yàn),討論技術(shù), 大家一起交流學(xué)習(xí)成長(zhǎng)!

推薦閱讀

1.直擊2020——iOS 面試題大全(補(bǔ)充完整版)

2.“新”攜程,阿里,騰訊iOS面試常見(jiàn)問(wèn)題合集(附答案)

3.我是如何同時(shí)拿到阿里和騰訊offer的

4.騰訊&阿里&美團(tuán)&快手&字節(jié)等10公司面經(jīng)

5.騰訊社招iOS面試記錄

6.最新阿里騰訊頭條美團(tuán)等iOS面試總結(jié)

7.讓 BAT 的 Offer 不再難拿

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容