1. 程式人生 > >javascript/前端 有關陣列的面試題

javascript/前端 有關陣列的面試題

前言:近期面試被問到多個有關陣列的面試題,平時面試別人也喜歡考陣列相關的題目。在這裡舉幾個例子記錄一下。

陣列相關API常用的不多(ES5/6/7新增部分,使用時需要注意相容性),也簡單易懂,但組合使用起來會很靈活,出題方式多,向面試者描述也很容易被理解。
如果能熟練應用,平時寫程式碼的效率也能提高不少,經驗相對豐富的前端開發不可避免地會經常與資料打交道。總結起來就是很適合做面試題。。。

開始之前先推薦超實用的工具庫lodash,提供了很多實用的工具函式。

以下程式碼使用ES6語法,新版Chrome瀏覽器可以直接執行,不需要babel編譯。

// 一、將字串反向 'abc123' => '321cba'
// 很多不熟悉陣列api的小夥伴會回答 for迴圈。。。迴圈當然是可以的,兩年前我也這麼回答。。 // 加分回答 'abc123'.split('').reverse().join('')
// 二、打平巢狀陣列 [1, [2, [3], 4], 5] => [1, 2, 3, 4, 5]
// 我現場寫的程式碼:
const arr = [1,[2,[3],4],5]
function flatten(arr) {
    for (let i in arr) {
        if (Array.isArray(arr[i])) {
            arr.splice(i, 1
, ...flatten(arr[i])) } } return arr } flatten(arr) // 偶然發現 arr.toString() 或 arr.join() => '1,2,3,4,5' // 於是可以寫的簡便些 const arr = [1,[2,[3],4],5] arr.join() .split(',') .map(it => Number(it)) // 網上搜了下,還可以這麼寫。。。 const arr = [1, [2, [3], 4], 5] JSON.parse(`[${arr}]`) // 這個題面試官想考查的應該是遞迴和深度優先遍歷,上面第二、三種回答只適合應付元素為數字的場景,第一種回答討巧避開了深度優先遍歷過程,直接在原陣列上修改,並不推薦。
// 如果要有較好適應性,還是寫遞迴吧。同時可以參考下 [underscore flatten](http://www.css88.com/doc/underscore/docs/underscore.html) 的實現。
// 三、列印陣列全排列
// [1,2,3] => [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
// 沒有明確的遍歷界限時都使用遞迴吧,實際應用場景,若非尾遞迴形式需要考慮是否可能棧溢位。
// 採用遞迴需要重點考慮引數及返回值的設定,本例使用有副作用的方式實現,這樣實現邏輯上比較好理解,只有當滿足條件時新增一條排列,遞迴中的返回值用起來總感覺頭暈。。
function allRange (arr, path, res) {
    if (!arr.length) {
        res.push(path)
        return
    }
    arr.forEach((v, idx) => {
        const t = arr.slice()
        const p = path.slice()
        t.splice(idx, 1)
        p.push(v)
        allRange(t, p, res)
    })
}
var a = [1, 2, 3, 4]
const b = []
allRange(a, [], b)
console.log(b)
// 四、尋找兩個有序陣列最小相同元素
const a = [1, 2, 5, 9, 10]
const b = [3, 4, 6, 9, 10]

function findElement (a, b) {
    let i = j = 0
    while (i < a.length || j < b.length) {
        if (a[i] === b[j]) {
            return a[i]
        } else if (a[i] > b[j]) {
            j ++
        } else if (a[i] < b[j]) {
            i ++
        }
    }
    return null
}

console.log(findElement(a, b))
// => 9
// 看到這個題目第一想法是 遍歷第一個陣列,二分法查詢第二個。經面試官提醒,採用遊標,更加簡單易懂。
// 五、有序二維陣列尋找某元素座標
const data = [[1, 2, 5, 9, 10],
              [12, 22, 35, 49, 51],
              [61, 62, 75, 79, 81]]

const len = data[0].length
function findOffset (e, a, b) {
    if (a > b) return null 

    const offset = (b - a) / 2 + a

    // 對映位置偏移到座標
    const x = offset % len
    const y = ~~(offset / len)

    if (data[y][x] === e) {
        return [x, y]
    } else if (e > data[y][x]) {
        return findOffset(e, offset + 1, b)
    } else {
        return findOffset(e, a, offset - 1)
    }
}
findOffset(75, 0, len * data.length - 1)
// => [2, 2]

// 看到這個題目第一想法是打平陣列使用indexOf得到下標,再根據data[0].length對映到二維陣列的座標,只需要幾行程式碼就能解決。
// 本題考的是二分查詢,相對一維陣列,多了一個通過偏移量對映座標的過程。