電話號碼的字母組合

由操作實例已知結(jié)果

由輸入輸出實例筹裕,可知遍歷路徑醋闭,該遍歷路徑也是最好的路徑,因此只要依次遍歷每個輸出字符串即可
以23為例朝卒,遍歷路徑即為:"ad","ae","af","bd","be","bf","cd","ce","cf"证逻,兩外無順序要求

要尋找該路徑的遍歷模型

冒泡式遍歷無法實現(xiàn),因為無法確定輸入字母集合個數(shù)抗斤。但是可以發(fā)現(xiàn)如”ad“囚企,實際上是位置{0,1},”ae“也可以是位置{0,2}瑞眼,由此可得龙宏,遍歷路徑可以轉(zhuǎn)換為:
{0,1},{0,2},{0,3},{0,4},{1,0}...,至此可以為該路徑設(shè)計遍歷模型伤疙,可以使用一個可以獲取下一遍歷節(jié)點的迭代器银酗,該迭代器的next操作類似由{m,n}獲取{m,n+1},當(dāng)位置超出子母個數(shù)時徒像,可以修正該位置

偽代碼實現(xiàn)

  1. 設(shè)計位置pos結(jié)構(gòu)體黍特,用于表示{m,n}位置
  2. 寫遍歷框架,基本是調(diào)用迭代器遍歷
  3. 編寫迭代器next函數(shù)厨姚,基本邏輯為當(dāng)前位置+1衅澈,當(dāng)位置超出時修正
    至此可以寫代碼調(diào)試至作題完畢。

題解暫作記錄

package main

import "fmt"

var phoneLettersMap = map[string]string{
    "2": "abc",
    "3": "def",
    "4": "ghi",
    "5": "jkl",
    "6": "mno",
    "7": "pqrs",
    "8": "tuv",
    "9": "wxyz",
}

type Pos struct {
    index        int
    phoneLetters string
}

type PhoneResultIterator struct {
    pos []Pos
}

func (phoneResultIterator *PhoneResultIterator) next() *PhoneResultIterator {
    phoneResultIterator.pos[0].index++

    for i, pos := range phoneResultIterator.pos {
        // 若當(dāng)前位數(shù)超出對應(yīng)子母串位數(shù)谬墙,修正當(dāng)前為0今布,下一位加1
        if pos.index > len(pos.phoneLetters)-1 {
            // 若修正位數(shù)時為最后一位经备,終止
            if i >= len(phoneResultIterator.pos)-1 {
                return nil
            }

            phoneResultIterator.pos[i].index = 0
            phoneResultIterator.pos[i+1].index++
        }
    }

    return phoneResultIterator
}

func (phoneResultIterator *PhoneResultIterator) toString() string {
    var letterResString string = ""
    for _, pos := range phoneResultIterator.pos {
        letterResString = letterResString + string(pos.phoneLetters[pos.index])
    }

    return letterResString
}

func letterCombinations(digits string) []string {
    stringRes := make([]string, 0)

    if len(digits) <= 0 {
        return stringRes
    }

    // 初始化結(jié)果迭代器
    phoneResultIterator := &PhoneResultIterator{}
    phoneResultIterator.pos = make([]Pos, len(digits))
    for i, _ := range phoneResultIterator.pos {
        phoneResultIterator.pos[i].index = 0
        phoneResultIterator.pos[i].phoneLetters = phoneLettersMap[string(digits[i])]
    }

    // 遍歷結(jié)果集
    for phoneResultIterator != nil {
        stringRes = append(stringRes, phoneResultIterator.toString())
        phoneResultIterator = phoneResultIterator.next()
    }

    return stringRes
}

func main() {
    res := letterCombinations("274")
    fmt.Print(res)
}

看題解發(fā)現(xiàn)對于遍歷所有集合有通用解決模型:回溯

回溯專題

后面會做一個回溯的專題訓(xùn)練

回溯基本模型

查閱資料發(fā)現(xiàn)回溯有通用的樸素模型:

result = []
def backtrack(路徑, 選擇列表):
    if 滿足結(jié)束條件:
        result.add(路徑)
        return

    for 選擇 in 選擇列表:
        做選擇
        backtrack(路徑, 選擇列表)
        撤銷選擇
回溯經(jīng)典問題

回溯經(jīng)典問題包括:

  1. N皇后回溯
  2. 01背包
  3. 樹深度優(yōu)先遍歷
  4. 樹廣度優(yōu)先遍歷
電話號碼子母組合回溯解法
回溯解法
package main

import "fmt"

var phoneLettersMap = map[string][]string{
    "2": {"a", "b", "c"},
    "3": {"d", "e", "f"},
    "4": {"g", "h", "i"},
    "5": {"j", "k", "l"},
    "6": {"m", "n", "o"},
    "7": {"p", "q", "r", "s"},
    "8": {"t", "u", "v"},
    "9": {"w", "x", "y", "z"},
}
var stringRes []string
var list [][]string

func backTrace(track string, row int) bool {
    // 遞歸基
    if row == len(list) {
        stringRes = append(stringRes, track)
        return true
    }

    // 遍歷列表
    for _, letter := range list[row] {
        // 選擇:得到新track
        track := track + letter

        // 列表:得到下一級決策組,觸發(fā)bt調(diào)用
        backTrace(track, row+1)

        // 取消選擇track
        track = track[0 : len(track)-1]
    }

    return true
}

func letterCombinations(digits string) []string {
    stringRes = make([]string, 0)
    list = make([][]string, 0)

    // 特殊case
    if digits == "" {
        return stringRes
    }

    // 初始化遍歷列表
    for i := 0; i < len(digits); i++ {
        list = append(list, phoneLettersMap[string(digits[i])])
    }

    // 遍歷
    backTrace("", 0)

    return stringRes
}

func main() {
    res := letterCombinations("273")
    fmt.Print(res)
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末部默,一起剝皮案震驚了整個濱河市侵蒙,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌傅蹂,老刑警劉巖纷闺,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異份蝴,居然都是意外死亡犁功,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進(jìn)店門婚夫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來浸卦,“玉大人,你說我怎么就攤上這事案糙∠尴樱” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵时捌,是天一觀的道長澄步。 經(jīng)常有香客問我梁呈,道長剂桥,這世上最難降的妖魔是什么刘莹? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任蛤奥,我火速辦了婚禮佳镜,結(jié)果婚禮上蟀伸,老公的妹妹穿的比我還像新娘缅刽。我一直安慰自己,他們只是感情好衰猛,可當(dāng)我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布啡省。 她就那樣靜靜地躺著髓霞,像睡著了一般畦戒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上障斋,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天垃环,我揣著相機與錄音,去河邊找鬼被济。 笑死涧团,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的泌绣。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼元媚,長吁一口氣:“原來是場噩夢啊……” “哼苗沧!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起甥角,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤嗤无,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后当犯,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體割疾,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年拓诸,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片趣钱。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡胚宦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出井联,到底是詐尸還是另有隱情,我是刑警寧澤烙常,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布蚕脏,位于F島的核電站,受9級特大地震影響驼鞭,放射性物質(zhì)發(fā)生泄漏尺碰。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一洛心、第九天 我趴在偏房一處隱蔽的房頂上張望题篷。 院中可真熱鬧,春花似錦悼凑、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至瘟忱,卻和暖如春苫幢,著一層夾襖步出監(jiān)牢的瞬間韩肝,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工哀峻, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留剩蟀,地道東北人切威。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像先朦,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子喳魏,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容