[算法] 電話號碼分身 (小米2017 秋招真題)[JavaScript]

題目描述javascript

繼MIUI8推出手機分身功能,MIUI計劃推出一個電話號碼分身得功能:首先將電話號碼中的每一個數字加上8取個位,而後使用對應得大寫字母代替 ("ZERO", "ONE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN", "EIGHT", "NINE"), 而後隨機打亂這些字母,所生成得字符串即爲電話號碼對應得分身。java

例子:
輸入 => 輸出
EIGHT => 0
ZEROTWOONE => 234
OHWETENRTEO => 345
OHEWTIEGTHENRTEO => 0345算法

這道題是輸入一個字符串,映射到一個數字串。
映射題個人習慣是先嚐試用字典的方式作,那麼接下來開始作這道題:數組

10個數字與其英文單詞一一對應,那麼這些詞能不能作些文章呢?code

咱們能夠發現,在這十個數字的英文單詞中,字符 Z 只存在於 ZEROW 只存在於 TWO,以此類推。
因此如今一旦在字符串中發現 Z,咱們就能夠說存在 0
咱們在這裏把 Z 稱做 特徵字符, ZERO 稱做 字符值, 0 稱爲 數字值
那麼,咱們能夠獲得一組映射:排序

{
    Z: ['ZERO', 0],
    W: ['TWO', 2],
    U: ['FOUR', 4],
    X: ['SIX', 6],
    G: ['EIGHT', 8]
}

所以0, 2, 4, 6, 8已經處理好了,如今還剩下 1, 3, 5, 7, 9
仔細分析能夠發現,字符O在這五個數字的英文中,只存在於ONE;字符F只存在於FIVE中,以此類推。
那麼,咱們又能夠獲得一組映射:ip

{
    O: ['ONE', 1],
    T: ['THREE', 3],
    F: ['FIVE', 5],
    S: ['SEVEN', 7]
}

爲何這裏沒有9的映射呢?由於 NINEN, I, E1, 3, 5, 7中都有出現,這裏咱們就先空着。字符串

注意
這裏的兩個映射關係是不能夠合併的,想一想爲何?it

那麼這些映射關係有什麼用呢?這裏就要用到字典(dict)啦。
咱們能夠把輸入的字符串,轉換爲一個字典結構,key 是字符, value 是這個字符在整個字符串中出現的次數。console

例如:

"OHEWTIEGTHENRTEO"

var dict = {
    E: 4,
    T: 3,
    O: 2,
    H: 2,
    I: 1,
    G: 1,
    W: 1,
    N: 1,
    R: 1
}

而後咱們遍歷這個字典:

[{
    Z: ['ZERO', 0],
    W: ['TWO', 2],
    U: ['FOUR', 4],
    X: ['SIX', 6],
    G: ['EIGHT', 8]
},{
    O: ['ONE', 1],
    T: ['THREE', 3],
    F: ['FIVE', 5],
    S: ['SEVEN', 7]
}].map(map => {
    Object.keys(dict).map(key => {
        /** 檢查當前字符是否在映射表中
         * 在的話檢查字典中當前字符的數量是否仍然大於0
         */
        map[key] && dict[key] > 0 &&
        /**
         * 把映射關係中的字面值取出並拆解爲一個字符數組,
         * 遍歷這個字符數組,將字典中該字符的計數減去1,即消化了這個字面值
         */
        map[key][0].split('').map(char => dict[char] -= 1) &&
        // 把消化的數字值打出來
        console.log(map[key][1])
    })
})

/**
 * 2
 * 8
 * 1
 * 3
 */

但是題目說明 OHEWTIEGTHENRTEO 的輸出值應該是 0345呀,哪裏出錯了呢?

注意題目中的一句話

首先將電話號碼中的每一個數字加上8取個位

也就是說,咱們打出來的值還須要對這個 加8取個位 進行逆向。
有幾種方法,一是在打印時對 map[key][1] 進行處理:

num => num - 8 >= 0 ? num - 8 : num + 2

或者,我這裏用了偷懶的辦法,還記得咱們映射表中有個數字值嗎?我人工替換了 :P

[{
    Z: ['ZERO', 2],
    W: ['TWO', 4],
    U: ['FOUR', 6],
    X: ['SIX', 8],
    G: ['EIGHT', 0]
},{
    O: ['ONE', 3],
    T: ['THREE', 5],
    F: ['FIVE', 7],
    S: ['SEVEN', 9
}].map(map => {
    Object.keys(dict).map(key => {
        map[key] && dict[key] > 0 &&
        map[key][0].split('').map(char => dict[char] -= 1) &&
        console.log(map[key][1])
    })
})

/**
 * 4
 * 0
 * 3
 * 5
 */

那麼如今只須要把輸出值進行一下正序排序便可:

var output = [];

[{ Z: ['ZERO', 2], W: ['TWO', 4], U: ['FOUR', 6], X: ['SIX', 8], G: ['EIGHT', 0]
},{ O: ['ONE', 3], T: ['THREE', 5], F: ['FIVE', 7], S: ['SEVEN', 9}].map(map => {
    Object.keys(dict).map(key => {
        map[key] && dict[key] > 0 &&
        map[key][0].split('').map(char => dict[char] -= 1) &&
        output.push(map[key][1])
    })
})

/* 
 * 還記得咱們把 9 的處理留空了嗎?如今要補上啦~
 * 9 的英文 NINE 你只須要隨意檢查前邊過濾後的字典是否還存在 N I E 任意一個字符便可
 * 我選擇的是判斷 E
 * 輸入的9對應的輸出應該是1,還記得爲何嗎?
 */
//if (dict['E'] && dict['E'] > 0) output.push(1)

/**
 * 2017.09.19 08:36 更新:
 * 以前只判斷了是否還存在9,可是忘了多個9同時存在的狀況,那麼須要作以下改進:
 */
 dist['E'] && // 檢查是否還存在特徵字符 E,在通過前面的映射關係過濾後,還剩下幾個E,就還有幾個9
 (output = output.concat(Array(dist['E']).fill(1))) //純js技巧,快速生成指定大小的數組並填充一個值

output.sort()
console.log(output) // 0 3 4 5

雖說本文標題有個 [算法] 前綴,不過這個寫法徹底沒考慮什麼複雜度之類的東西 ORZ

相關文章
相關標籤/搜索