Word Ladder

Q:

Given two words (start and end), and a dictionary, find the length of shortest transformation sequence from start toend, such that:

  1. Only one letter can be changed at a time
  2. Each intermediate word must exist in the dictionary

For example,

Given:
start = "hit"
end = "cog"
dict = ["hot","dot","dog","lot","log"]

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.

A:

再次中招,自己用提供的测试里测试正确,到了leetcode测试就全是2, 我2了。我没招了,也没觉得我的代码有神马问题。转换成图,求最短路径。

#include <queue>
#define MAX_DIS 0x7fffff

class Solution {
 public:
  int ladderLength(string start, string end, unordered_set<string> &dict) {
    // Start typing your C/C++ solution below
    // DO NOT write int main() function
    GenerateGragh(start, end, dict);
    return Dijkstra(0, 1);
  }

 private:
  void GenerateGragh(const string& start, const string& end,
      unordered_set<string> &dict) {
    if (dict.find(start) != dict.end()) dict.erase(start);
    if (dict.find(end) != dict.end()) dict.erase(end);
    dises_.clear();
    nodes_.push_back(start);
    nodes_.push_back(end);
    for (unordered_set<string>::iterator iter = dict.begin(); iter != dict.end(); ++iter) {
      nodes_.push_back(*iter);
    }
    dises_.resize(nodes_.size());

    for (int i = 0; i < nodes_.size(); ++i) {
      for (int j = i + 1; j < nodes_.size(); ++j) {
        int dis = CalcDistance(nodes_[i], nodes_[j]);
        if (dis > 1) continue;
        dises_[i].push_back(NodeDistance(j, dis));
        dises_[j].push_back(NodeDistance(i, dis));
      }
    }
  }

  int CalcDistance(const string& src, const string& dst) {
    int dis = 0;
    for (int i = 0; i < src.length(); ++i) {
      if (src[i] != dst[i]) dis++;
      if (dis >= 2) return MAX_DIS;
    }
    return dis;
  }

  int Dijkstra(int src, int dst) {
    priority_queue<NodeDistance, vector<NodeDistance>, greater<NodeDistance> > dis_q;
    unordered_set<int> closet;
    vector<int> min_dises;
    min_dises.resize(dises_.size(), MAX_DIS);
    min_dises[src] = 0;
    closet.insert(src);
    for (int i = 0; i < dises_[src].size(); ++i) {
      dis_q.push(dises_[src][i]);
    }
    while (!dis_q.empty()) {
      NodeDistance cur = dis_q.top();
      dis_q.pop();
      if (closet.find(cur.dst) != closet.end()) continue;
      min_dises[cur.dst] = cur.dis;
      if (cur.dst == dst) break;
      closet.insert(cur.dst);
      for (int i = 0; i < dises_[cur.dst].size(); ++i) {
        dis_q.push(NodeDistance(dises_[cur.dst][i].dst, cur.dis + dises_[cur.dst][i].dis));
      }
    }
    return min_dises[dst] == MAX_DIS ? 0 : min_dises[dst] + 1;
  }

 private:
  class NodeDistance {
   public:
    int dst;
    int dis;
    NodeDistance(int dst_idx, int distance):dst(dst_idx), dis(distance) {}
    friend bool operator < (const NodeDistance& src, const NodeDistance& dst) {
      return src.dis < dst.dis;
    }
    friend bool operator > (const NodeDistance& src, const NodeDistance& dst) {
      return src.dis > dst.dis;
    }
  };

  vector<vector<NodeDistance> > dises_;
  vector<string> nodes_;
};

 

posted @ 2013-07-01 21:24  dmthinker  阅读(115)  评论(0)    收藏  举报