算法題目5:挑選電腦

題目:小特最近要開學了,他打算入學前買一臺筆記本電腦。小特看中了戴爾和微軟的超薄本,他打算 先找兩個品牌價格最接近的型號比較一下性能。他已經在電商網站上找到了兩個品牌各個型號的 價格, 請你寫程序幫助他找到價格差最小的兩款!
輸入:
第一行第 1 個數爲 戴爾電腦型號的數量 n,接着有 n 個數表示每個型號的價格。
第二行第 1 個數爲 微軟電腦型號的數量 m,接着有m個數表示每個型號的價格。 每行數字用空格分割。
電腦價格爲大於 0 小於 2147483647 的整數
輸出:
輸出價格差最小的兩款電腦的下標,用空格分開
樣例輸入:
5 3998 4698 6698 8898 7798
4 2068 5688 10198 5288
樣例輸出:
1 3(價格最接近的是 4698 和 5288,下標分別爲 1 和 3)
提示:
暴力 O(mn)的方法會視爲錯誤

思路:二路歸併

解法:

function generateNumbers(n){
    let arr = []
    for (let i = 0; i < n; i++) {
        let num = parseInt(Math.random() * 100000000)
        arr.push(num)
    }
    return arr
}

function cmpPrice(a, b) {
    return a.price - b.price
}

// 查找arr1 和 arr2 最相近的兩個數的下標
function findNearest(arr1, arr2) {
    let x = [], y = []
    for (let i = 0; i < arr1.length; i++) {
        x.push({price:arr1[i], index:i})
    }
    for (let i = 0; i < arr2.length; i++) {
        y.push({price:arr2[i], index:i})
    }
    // 按價格排序 複雜度O(mlgm)+O(nlgn)
    x.sort(cmpPrice)
    y.sort(cmpPrice)

    let a = x.shift()
    let b = y.shift()
    let delta = 2147483647 // 歷史最小差值
    let idx1 = 0 // 歷史最小差值對應的arr1.index
    let idx2 = 0 // 歷史最小差值對應的arr2.index

    // 兩路歸併, 複雜度O(m+n)
    while (true) {
        let d = Math.abs(a.price - b.price)
        if (d == 0) { // 兩個值相等,這是最小的差值了,直接返回結果
            return [a.index, b.index]
        }
        // 如果當前的差值比歷史最小差值還小,那麼就更新下
        if (d < delta) {
            idx1 = a.index
            idx2 = b.index
            delta = d
        }
        // 兩個隊列都空了,返回
        if (x.length == 0 && y.length == 0) {
            return [idx1, idx2]
        }
        if (x.length == 0) {        // x空了,那麼從y取一個
            b = y.shift()
        }else if (y.length == 0) {  // y空了,那麼從x取一個
            a = x.shift()
        }else if (a.price < b.price) {  // 誰小從誰那取
            a = x.shift()
        }else {
            b = y.shift()
        }
    }

    // 總複雜度O(mlgm)+O(nlgn) + O(m+n) 即 O(mlgm) 假設m>n
}

// 查找arr1 和 arr2 最相近的兩個數的下標
// 窮舉解法,用來驗證答案
function exhaustive(arr1, arr2) {
    let delta = 2147483647
    let idx1 = 0
    let idx2 = 0
    for (let i = 0; i < arr1.length; i++) {
        for (let j = 0; j < arr2.length; j++) {
            let d = Math.abs(arr1[i] - arr2[j])
            if (d < delta) {
                idx1 = i
                idx2 = j
                delta = d
            }
        }
    }
    return [idx1, idx2]
}

function solve() {
    let arr1 = generateNumbers(10)
    let arr2 = generateNumbers(15)
    console.log("arr1 =",arr1)
    console.log("arr2 =",arr2)

    let result = findNearest(arr1, arr2)
    console.log('當前算法結果:',result, '左:',arr1[result[0]], '右:', arr2[result[1]], '差值', Math.abs(arr1[result[0]]-arr2[result[1]]))

    let result2 = exhaustive(arr1, arr2)
    console.log('窮舉算法結果:',result2, '左:',arr1[result2[0]], '右:', arr2[result2[1]], '差值', Math.abs(arr1[result2[0]]-arr2[result2[1]]))
}

solve()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章