LeetCode 212. 单词搜索 II 字典树 回溯 C++

描述

给定一个二维网格 board 和一个字典中的单词列表 words,找出所有同时在二维网格和字典中出现的单词。

单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。

示例:

输入:
words = [“oath”,“pea”,“eat”,“rain”] and board =
[
[‘o’,‘a’,‘a’,‘n’],
[‘e’,‘t’,‘a’,‘e’],
[‘i’,‘h’,‘k’,‘r’],
[‘i’,‘f’,‘l’,‘v’]
]

输出: [“eat”,“oath”]
说明:
你可以假设所有输入都由小写字母 a-z 组成。

提示:

你需要优化回溯算法以通过更大数据量的测试。你能否早点停止回溯?
如果当前单词不存在于所有单词的前缀中,则可以立即停止回溯。什么样的数据结构可以有效地执行这样的操作?散列表是否可行?为什么? 前缀树如何?如果你想学习如何实现一个基本的前缀树,请先查看这个问题: 实现Trie(前缀树)。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/word-search-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

分析

提示了使用字典树
可以先将words里的词组成字典树,然后在board里依次找,只要board当前字母是在字典树root下面的分支里,就可以递归的去找
找的过程中,如果中途字典树走不下去了就返回,已经是存在的单词了就添加(但不返回,因为aaa是,aaab可能也是),在四个方向里找,找到可用的就继续递归向下

代码

class Solution {
public:
	struct Node {
		bool isflag = false;
		Node * next[27] = {};
	};
	setres; //防止结果有重复,多次查到同一个词
	vectorans;
	Node * root;
	vectordirx{ 0,0,1,-1 };
	vectordiry{ 1,-1,0,0 };
	bool flag;
	//组织字典树
	void createtree(vector&words) {
		root = new Node();
		
		for (auto w : words) {
			Node * p = root;
			for (int i = 0; i < w.length(); i++) {
				if (p->next[w[i] - 'a'] == NULL) {
					p->next[w[i] - 'a'] = new Node();
				}
				p = p->next[w[i] - 'a'];
			}
			p->isflag = true;
		}
	}
	void backtrack(vector>&board,vector>visited, int row, int col, Node*roott, string cur) {
		cur += board[row][col];
		roott = roott->next[board[row][col] - 'a'];
		if (!roott)return; //找不下去了
		if (roott->isflag == true)
		{
			//ans.push_back(cur);
			res.insert(cur);
			flag = true;
			//return;
		}
		visited[row][col] = true;
		
		for (int i = 0; i < 4; i++) {
			//if (flag == true)
				//return;
			int nx = row + dirx[i];
			int ny = col + diry[i];
			if (nx < 0 || ny < 0 || nx >= board.size() || ny >= board[0].size())
				continue;
			if (visited[nx][ny] == false) {
				backtrack(board, visited, nx, ny, roott, cur);
				//visited[nx][ny] = false;
				//cur.pop_back();
			}
		}
		
	}
	vector findWords(vector>& board, vector& words) {
		
		if (board.size() == 0 || words.size() == 0)
			return ans;
		createtree(words);
		
		for (int i = 0; i < board.size(); i++) {
			for (int j = 0; j < board[i].size(); j++) {
				Node * p = root; //每次查看是否符合root下的子分支
				flag = false;
				if (p->next[board[i][j] - 'a']) {
					vector>visited{ board.size(),vector(board[0].size(),false) };
					backtrack(board, visited, i, j, p, "");
				}
			}
		}
		set::iterator it;
		for (it = res.begin(); it != res.end(); it++)
			ans.push_back(*it);
		return ans;
	}
};

你可能感兴趣的:(算法,leetcode,回溯)