[Leetcode] 17, 127, 126

17. Letter Combinations of a Phone Number

Given a digit string, return all possible letter combinations that the number could represent.

A mapping of digit to letters (just like on the telephone buttons) is given below.

Input:Digit string "23"
Output: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].

Note:
Although the above answer is in lexicographical order, your answer could be in any order you want.

Solution: 对于每一位遍历每种可能性。

Code(递归):

class Solution {
public:
    vector<string> letterCombinations(string digits) {
        vector<string> ans;
        if(digits.size()==0) return ans;
        string path;
        letterCombinations(0, digits, path, ans);
        return ans;
    }
private:
    vector<string> m{"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
    void letterCombinations(int index, string& digits, string& path, vector<string>& ans){
        if(index==digits.size()){
            ans.push_back(path);
            return;
        }
        int number = digits[index]-'0';
        for(int i=0; m[number][i]; i++){
            path.push_back(m[number][i]);
            letterCombinations(index+1, digits, path, ans);
            path.pop_back();
        }
    }
};

Code(迭代):

class Solution {
public:
    const vector<string> m{"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
    vector<string> letterCombinations(string digits) {
        vector<string> ans;
        if(digits.size()==0) return ans;
        
        ans.push_back("");
        for(int i=0; i<digits.size(); i++){
            
            int size = ans.size();
            for(int j=0; j<size; j++){
                
                string s = ans[0];
                ans.erase(ans.begin());
                
                int index = digits[i]-'0';
                for(int t=0; m[index][t]; t++){
                    s.push_back(m[index][t]);
                    ans.push_back(s);
                    s.pop_back();
                }
            }
            
        }
        return ans;
    }
};




127. Word Ladder

Given two words (beginWord and endWord), and a dictionary's word list, find the length of shortest transformation sequence frombeginWord to endWord, such that:

  1. Only one letter can be changed at a time.
  2. Each transformed word must exist in the word list. Note that beginWord is not a transformed word.

For example,

Given:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log","cog"]

As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",
return its length 5.

Note:

  • Return 0 if there is no such transformation sequence.
  • All words have the same length.
  • All words contain only lowercase alphabetic characters.
  • You may assume no duplicates in the word list.
  • You may assume beginWord and endWord are non-empty and are not the same.

UPDATE (2017/1/20):
The wordList parameter had been changed to a list of strings (instead of a set of strings). Please reload the code definition to get the latest changes.

Solution: 广度优先搜索,一层层的搜索相邻单词,使用位向量visited记录访问过的单词去重。

Code:

class Solution {
public:
    int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
        if(beginWord==endWord) return 1;
        //广搜
        vector<bool> visited;//不要使用vector<bool> visited(false, wordList.size*())的方式初始化,不知为何会出bug
        for(int i=0; i<wordList.size(); i++) visited.push_back(false); //直接push_back
        queue<pair<int,int>> q;//(wordIndex,step)
        for(int t=0; t<wordList.size(); t++){
            int count = 0;
            for(int j=0; j<wordList[t].size(); j++){
                if(beginWord[j]!=wordList[t][j]){
                    count++;
                    if(count>2) break;
                }
                    
            }
            if(count==1){
                q.push(make_pair(t,2));
                visited[t] = true;
            }
        }
        while(!q.empty()){
            if(wordList[q.front().first]==endWord){
                return q.front().second;
            }
            for(int t=0; t<wordList.size(); t++){
                if(visited[t]) continue;
                int count = 0;
                for(int j=0; j<wordList[t].size(); j++){
                    if(wordList[q.front().first][j]!=wordList[t][j]){
                        count++;
                        if(count>2) break;
                    }
                }
                if(count==1){
                    q.push(make_pair(t,q.front().second+1));
                    visited[t] = true;
                }
            }
            q.pop();
        }
        return 0;
    }
};



126. Word Ladder II

Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformation sequence(s) from beginWordto endWord, such that:

  1. Only one letter can be changed at a time
  2. Each transformed word must exist in the word list. Note that beginWord is not a transformed word.

For example,

Given:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log","cog"]

Return

  [
    ["hit","hot","dot","dog","cog"],
    ["hit","hot","lot","log","cog"]
  ]

Note:

  • Return an empty list if there is no such transformation sequence.
  • All words have the same length.
  • All words contain only lowercase alphabetic characters.
  • You may assume no duplicates in the word list.
  • You may assume beginWord and endWord are non-empty and are not the same.

UPDATE (2017/1/20):
The wordList parameter had been changed to a list of strings (instead of a set of strings). Please reload the code definition to get the latest changes.

Solution: 这题解法思路跟上一题类似,只是注意三点:1、去重的方式必须要保留所有的最短路径;2、记录下路径的方式;3、退出循环的时机。

Code:

class Solution {
public:
    vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) {
        vector<vector<string>> ans;
        if(beginWord==endWord){
            ans.push_back(vector<string> {beginWord});
            return ans;
        }
        
        //广搜
        wordList.insert(wordList.begin(), beginWord);
        vector<bool> visited;//不要使用vector<bool> visited(false, wordList.size*())的方式初始化,不知为何会出bug
        for(int i=0; i<wordList.size(); i++) visited.push_back(false); //直接push_back
        unordered_set<int> cur, next;//(wordIndex,step) //使用set去重
        cur.insert(cur.end(), 0);
        int level = 1;
        bool found = false;
        unordered_map<int,vector<int>> father;//记录全部的路径
        int target = find(wordList.begin(), wordList.end(), endWord) - wordList.begin();
        if(target==wordList.size()) return ans;
        int k = 20;
        while(!cur.empty() && !found){
            for(auto i:cur) visited[i] = true;//防止指向同一层或者上一层的单词
            while(!cur.empty()){
                cout<<level<<' '<<wordList[*cur.begin()]<<": ";
                for(int t=0; t<wordList.size(); t++){
                    if(visited[t]) continue;
                    int count = 0;
                    for(int j=0; j<wordList[t].size(); j++){
                        if(wordList[*cur.begin()][j]!=wordList[t][j]){
                            count++;
                            if(count>2) break;
                        }
                    }
                    if(count==1){
                        cout<<wordList[t]<<' ';
                        next.insert(next.end(),t);
                        father[t].push_back(*cur.begin());
                        if(t==target) found = true;
                    }
                }
                cout<<endl;
                cur.erase(cur.begin());
            }
            level++;
            swap(cur, next);
        }
        vector<string> path;
        if(found) setPath(father, target, wordList, path, ans);
        return ans;
    }
private:
    void setPath(unordered_map<int,vector<int>>& father, int target, vector<string>& wordList, 
                 vector<string>& path, vector<vector<string>>& ans){
        path.insert(path.begin(), wordList[target]);
        if(target==0){
            ans.push_back(path);
        }else{
            for(int i=0; i<father[target].size(); i++){
                setPath(father, father[target][i], wordList, path, ans);
            }
        }
        path.erase(path.begin());
        return;
    }
};



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值