leetcode word ladder 2

本文详细介绍了LeetCode上单词阶梯II问题的多种解法,包括使用图论中的BFS算法、DFS算法以及双向搜索策略等。通过不断优化算法,最终实现了高效的AC代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


15-05-10 更新,按照最下面的解法进行优化,得到AC代码,并且比他快。值得一开心。

class WordNode {
public:
  string value;
  unordered_set<WordNode*> Parents;
  WordNode(string v) :value(v) { }
};

vector<vector<string>> gres;
vector<string> gtmp;

void checkOneNode(string end, WordNode* node) {
  gtmp.push_back(node->value);
  if (node->value == end) {
    vector<string> tmp_res = gtmp;
    gres.push_back(tmp_res);
    gtmp.pop_back();
    return;
  }

  for (auto it : node->Parents) {
    checkOneNode(end, it);
  }

  gtmp.pop_back();
}

vector<vector<string>> findLadders(
    string start, string end,
    unordered_set<string> &dict) {
  dict.insert(start);
  WordNode* start_node = NULL;

  WordNode* end_node = new WordNode(end);
  unordered_map<string, WordNode*> curr_flow, next_flow;
  curr_flow[end] = end_node;
  string current_word = "";

  int n = end.length(), ch;
  string a;

  //construct a reverse tree
  //first create end node, then find words can transform to end, 
  //and create edge(word, end), do it recursively until find start.
  bool done = false;//if find the start, stop
  while (!done && !curr_flow.empty()) {
    for (auto it : curr_flow) {
      current_word = it.first;
      for (int j = 0; j < n; j++) {
        ch = current_word[j] - 'a';
        for (int k = 0; k < 26; k++) {
          if (k == ch) continue;
          current_word[j] = 'a' + k;
          if (dict.find(current_word) != dict.end()) {
            //first time add a word to the tree, create it's node
            if (next_flow[current_word] == NULL) {
              next_flow[current_word] = new WordNode(current_word);
              if (current_word == start) {
                done = true;
                start_node = next_flow[current_word];
              }
            }
            //create edge(new_word, current_layer_word)
            next_flow[current_word]->Parents.insert(it.second);
          }
        }//end of 26 letters
        current_word[j] = 'a' + ch;
      }//end of word's length
    }//end of curr_flow
    curr_flow = next_flow;
    next_flow.clear();
    for (auto it : curr_flow) dict.erase(it.first);
  }
  if (!done) {
    return vector<vector<string>>();
  }
  //deep first search for ladders
  checkOneNode(end, start_node);
  return gres;
}



做了三天。从一开始的只会用遍历,到后来优化遍历条件,再到尝试用图和BFS做,真是脑子不够了。

还是不够AC,太慢了。

struct MapNode{
public:
	bool added;
	string val;
	list<MapNode *> neighbors;
	vector<list<MapNode *>> routes;
	MapNode(string s) :added(false), val(s){}
	void RemoveNeighbor(string s);
};


vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict) {
	vector<vector<string>> res;
	string a;
	int n = start.length();
	int i = 0, difcount = 0;
	while (i < n){
		if (start[i] != end[i++])difcount++;
		if (difcount>1)break;
	}
	if (difcount == 1)
	{
		vector<string> tmp;
		tmp.push_back(start), tmp.push_back(end);
		res.push_back(tmp);
		return res;
	}

	MapNode *sp = new MapNode(start);
	MapNode *ep = new MapNode(end);
	list<MapNode *> nodelist;
	nodelist.push_back(sp), nodelist.push_back(ep);
	
	//build map
	for (auto it : dict){
		MapNode *tmp = new MapNode(it);
		for (auto qit : nodelist){
			i = 0, difcount = 0;
			a = qit->val;
			while (i < n){
				if (a[i] != it[i++])difcount++;
				if (difcount > 1)break;
			}
			if (difcount == 1)
			{
				qit->neighbors.push_back(tmp);
				tmp->neighbors.push_back(qit);
			}
		}
		nodelist.push_back(tmp);
	}

	/**/
	//bsf
	queue<MapNode *> q;
	sp->added = true;
	list<MapNode *> st;
	st.push_back(sp);
	sp->routes.push_back(st);
	q.push(sp);
	int count = 1;
	while (q.size()>0){
		MapNode *qtmp = q.front();
		q.pop();
		if (count == 0){
			count = q.size();
		}
		count--;
		for (auto qit = qtmp->neighbors.begin(); qit != qtmp->neighbors.end(); qit++){
			MapNode *tmp = *qit;
			tmp->neighbors.remove(qtmp);
			if (tmp->routes.size() == 0)
			{
				for (auto rit : qtmp->routes){
					rit.push_back(tmp);
					tmp->routes.push_back(rit);
				}
			}
			else{
				list<MapNode *> prelist = qtmp->routes.front();
				list<MapNode *> nextlist = tmp->routes.front();
				if (prelist.size() + 1 > nextlist.size())continue;
				if (prelist.size() + 1 < nextlist.size())tmp->routes.clear();
				for (auto rit : qtmp->routes){
					rit.push_back(tmp);
					tmp->routes.push_back(rit);
				}
			}
			if (!tmp->added){
				tmp->added = true;
				q.push(tmp);
			}
		}

		if (count == 0 && ep->routes.size()>0)
		{
			break;
		}
	}

	for (auto rit : ep->routes)
	{
		vector<string> tmp;
		for (auto mnode : rit){
			tmp.push_back(mnode->val);
		}
		res.push_back(tmp);
	}
	
	return res;
}



2015-05-10更新一个思路,比之前好一些,不过还是不够AC。

bool isAlike(string a, string b) {
  int c = 0, n = a.length();
  for (size_t i = 0; i < n; i++) {
    if (a[i] != b[i]) c++;
    if (c > 1) return false;
  }
  return c == 1;
}
class WordNode {
public:
  string value;
  unordered_set<WordNode*> Parents;
  WordNode(string v) :value(v) { }
};

vector<vector<string>> gres;
vector<string> gtmp;

void checkOneNode(string end, WordNode* node) {
  gtmp.push_back(node->value);
  if (node->value == end) {
    vector<string> tmp_res = gtmp;
    gres.push_back(tmp_res);
    gtmp.pop_back();
    return;
  }

  for (auto it : node->Parents) {
    checkOneNode(end, it);
  }

  gtmp.pop_back();
}

vector<vector<string>> findLadders(
    string start, string end,
    unordered_set<string> &dict) {
  vector<vector<string>> path;
  vector<string> res;
  vector<vector<string>> ress;
  if (isAlike(start, end)) {
    res.push_back(start);
    res.push_back(end);
    ress.push_back(res);
    return ress;
  }
  swap(start, end);//trying to build a reverse tree
  unordered_set<WordNode*> vec_dict;
  int index = 0;
  for (auto dit : dict) {
    WordNode* curr_node = new WordNode(dit);
    vec_dict.insert(curr_node);
  }
  WordNode* end_node = new WordNode(end);
  vec_dict.insert(end_node);
  return ress;

  WordNode* root = new WordNode(start);
  WordNode* wn_pointer = root;
  unordered_set<WordNode*> flow[2];
  int curr_flow = 0, other_flow = 1;
  flow[curr_flow].insert(root);
  string current_word = "";

  int i, difcount, n = end.length();
  string a;

  //construct the tree
  bool done = false, empty = false;//if find the end, stop
  while (!done && !empty) {
    for (auto it : flow[curr_flow]) {
      current_word = it->value;
      empty = true;
      //find current_word's transformable words in dict
      for (auto dit : vec_dict) {
        i = 0;
        a = dit->value;
        
        while (i < n){
          if (a[i] != current_word[i++]) {
            a[i - 1] = current_word[i - 1];
            break;
          }
        }
        if (a == current_word) {
          empty = false;
          dit->Parents.insert(it);
          flow[other_flow].insert(dit);
          if (dit->value == end) {
            done = true;//if reach the end
          }
        }
      }//end of find current_word's transformable words
    }//end of curr_flow
    flow[curr_flow] = unordered_set<WordNode*>();
    curr_flow = other_flow;
    other_flow = 1 - curr_flow;
    for (auto it : flow[curr_flow]) vec_dict.erase(it);
    if (empty && !flow[curr_flow].empty()) empty = false;
  }
  if (!done) {
    return ress;
  }
  //deep first search for ladders
  checkOneNode(start, end_node);
  return gres;
}


看看别人怎么做的吧。


经过几天的不断学习(0 0),终于AC了。。 还是改进别人的代码做的。

class Solution {
public:
unordered_multimap<string, string> lmap;
vector<vector<string>> res;

void getPath(string curr, string end, vector<string> path){
	if (curr == end)
	{
		path.push_back(end);
		res.push_back(path);
		return;
	}

	path.push_back(curr);
	unordered_multimap<string, string>::iterator it;
	pair<unordered_multimap<string, string>::iterator, unordered_multimap<string, string>::iterator > range = lmap.equal_range(curr);
	for (it = range.first; it != range.second; it++)
	{
		getPath(it->second, end, path);
	}
	path.pop_back();
}


vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict) {
	
	string a;
	int n = start.length();

	//1. push end, find all next level words and push the pairs into lmap;
	//2. find all next level words and push the pairs into lmap until start in lmap;
	//3. find path and save in res

	unordered_set<string> last_layer, curr_layer;

	//unordered_set<string> levels[2];  //takes about double time
	//int currl = 0, prevl = 1;
	
	int itmp, i, j;
	string stmp;
	curr_layer.insert(end);
	dict.insert(start);
	bool flag = false;

	while (curr_layer.size() > 0 || last_layer.size() > 0)
	{
		for (unordered_set<string>::iterator it = last_layer.begin(); it != last_layer.end(); it++)
		{
			dict.erase(*it);
		}
		last_layer.clear();

		for (unordered_set<string>::iterator it = curr_layer.begin(); it != curr_layer.end(); it++)
		{
			for (i = 0; i < n; i++)
			{
				stmp = *it;
				itmp = stmp[i] - 'a';
				for (j = 1; j < 26; j++)
				{
					stmp[i] = (itmp + j) % 26 + 'a';
					if (dict.find(stmp) != dict.end())
					{
						lmap.insert(make_pair(stmp, *it));
						last_layer.insert(stmp);
					}
				}
			}
		}

		curr_layer = last_layer;

		if (curr_layer.count(start) > 0)
		{
			break;
		}
	}

	vector<string> path;
	if (lmap.size() > 0)getPath(start, end, path);

	return res;
}
    
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值