题目
回溯+深度优先遍历
代码一
class Solution {
List<String> res = new ArrayList<>();
boolean flag = false;
public List<String> findWords(char[][] board, String[] words) {
int row = board.length;
int col = board[0].length;
for(int k = 0;k < words.length;k++){
flag = false;
exist(board,words[k]);
}
return res;
}
public void exist(char[][] board,String word){
for(int i = 0;i < board.length;i++){
for(int j = 0;j < board[0].length;j++){
boolean[][] used = new boolean[board.length][board[0].length];
if(board[i][j] == word.charAt(0)){
dfs(board,i,j,used,word,0,new StringBuilder());
}
if(flag){
break;
}
}
if(flag){
break;
}
}
}
public void dfs(char[][] board,int i,int j,boolean[][]used,String word,int k,StringBuilder sb){
if(k == word.length()-1 && board[i][j] == word.charAt(k)){
sb.append(word.charAt(k));
res.add(sb.toString());
flag = true;
return;
}
if(board[i][j] == word.charAt(k)){
sb.append(word.charAt(k));
used[i][j] = true;
if(!flag && i-1 >= 0 && !used[i-1][j])
dfs(board,i-1,j,used,word,k+1,sb);
if(!flag && i+1 < board.length && !used[i+1][j])
dfs(board,i+1,j,used,word,k+1,sb);
if(!flag && j-1 >= 0 && !used[i][j-1])
dfs(board,i,j-1,used,word,k+1,sb);
if(!flag && j+1 < board[0].length && !used[i][j+1])
dfs(board,i,j+1,used,word,k+1,sb);
sb.deleteCharAt(sb.length()-1);
used[i][j] = false;
}else{
return;
}
}
}
这大概是性能最差
代码二
class Solution {
boolean flag = false;
public List<String> findWords(char[][] board, String[] words) {
List<String> res = new ArrayList<>();
for(int k = 0;k < words.length;k++){
if(exist(board,words[k])){
res.add(words[k]);
}
}
return res;
}
public boolean exist(char[][] board,String word){
for(int i = 0;i < board.length;i++){
for(int j = 0;j < board[0].length;j++){
if(board[i][j] == word.charAt(0)){
boolean[][] used = new boolean[board.length][board[0].length];
flag = false;
if(dfs(board,i,j,word,0,used)){
return true;
}
}
}
}
return false;
}
public boolean dfs(char[][] board,int i,int j,String word,int k,boolean[][] used){
if(i < 0 || i >= board.length || j < 0 || j >= board[0].length || used[i][j] == true || board[i][j] != word.charAt(k)){
return false;
}
if(k == word.length()-1){
flag = true;
return true;
}
if(!flag){
used[i][j] = true;
boolean up = dfs(board,i-1,j,word,k+1,used);
boolean down = dfs(board,i+1,j,word,k+1,used);
boolean left = dfs(board,i,j-1,word,k+1,used);
boolean right = dfs(board,i,j+1,word,k+1,used);
used[i][j] = false;
return (up||down||left||right);
}else{
return true;
}
}
}
代码三
class Solution {
public List<String> findWords(char[][] board, String[] words) {
int row = board.length;
int col = board[0].length;
List<String> res = new ArrayList<String>();
//先判断遍历的入口
//再判断这个入口是否包含这个单词
//包含则在res中加入这个单词
for(int i = 0;i < words.length;i++){
if(exist(board,words[i])){
res.add(words[i]);
}
}
return res;
}
private boolean exist(char[][] board, String word) {
for(int i = 0;i < board.length;i++){
for(int j = 0;j < board[0].length;j++){
if(dfs(board,i,j,word,0)){
return true;
}
}
}
return false;
}
private boolean dfs(char[][] board, int i, int j, String word, int index) {
if(i < 0 || i >= board.length || j < 0 || j >= board[0].length || board[i][j] != word.charAt(index)){
return false;
}
if(index == word.length()-1){
return true;
}
char temp = board[i][j];
board[i][j] = '$';
boolean up = dfs(board,i-1,j,word,index+1);
if(up) {
board[i][j] = temp;
return true;
}
boolean down = dfs(board,i+1,j,word,index+1);
if(down) {
board[i][j] = temp;
return true;
}
boolean left = dfs(board,i,j-1,word,index+1);
if(left) {
board[i][j] = temp;
return true;
}
boolean right = dfs(board,i,j+1,word,index+1);
if(right) {
board[i][j] = temp;
return true;
}
board[i][j] = temp;
return false;
}
}
重点:
1.不需要在遍历时存字符串(StringBuilder sb),如果board中存在word,直接返回true,添加该word即可。
前缀树
class Solution {
Trie root = new Trie();
List<String> res = new ArrayList<>();
public List<String> findWords(char[][] board, String[] words) {
//建前缀树
for(String s : words){
root.insert(s);
}
int row = board.length;
int col = board[0].length;
for(int i = 0; i < row;i++){
for(int j = 0;j < col;j++){
boolean[][] used = new boolean[row][col];
dfs(board,i,j,used,new StringBuilder());
}
}
return res;
}
public void dfs(char[][] board,int i, int j, boolean[][] used, StringBuilder sb){
if(i < 0 || i >= board.length || j < 0 || j >= board[0].length || used[i][j]){
return;
}
sb.append(board[i][j]);
used[i][j] = true;
if(root.search(sb.toString())){
if(!res.contains(sb.toString())){
res.add(sb.toString());
}
}
if(root.startsWith(sb.toString())){
dfs(board,i-1,j,used,sb);
dfs(board,i+1,j,used,sb);
dfs(board,i,j-1,used,sb);
dfs(board,i,j+1,used,sb);
}
sb.deleteCharAt(sb.length()-1);
used[i][j] = false;
return;
}
}
class Trie{
private Trie[] next = new Trie[26];
private boolean isEnd;
public Trie(){
}
public void insert(String word){
Trie root = this;
for(char a:word.toCharArray()){
if(root.next[a-'a']==null){
root.next[a-'a'] = new Trie();
}
root = root.next[a-'a'];
}
root.isEnd = true;
}
public Trie searchPrefix(String word){
Trie root = this;
for(char a : word.toCharArray()){
if(root.next[a - 'a']!=null){
root = root.next[a - 'a'];
}else{
return null;
}
}
return root;
}
public boolean search(String word){
Trie root = searchPrefix(word);
return root != null && root.isEnd;
}
public boolean startsWith(String word){
Trie root = searchPrefix(word);
return root != null;
}
}
想知道时间打败100%的解