LeetCode刷题:212. 单词搜索 II (golang版)

  • 题目描述
给定一个 m x n 二维字符网格 board 和一个单词(字符串)列表 words,找出所有同时在二维网格和字典中出现的单词。

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

 
示例 1:
输入:board = [["o","a","a","n"],["e","t","a","e"],["i","h","k","r"],["i","f","l","v"]], words = ["oath","pea","eat","rain"]
输出:["eat","oath"]

示例 2:
输入:board = [["a","b"],["c","d"]], words = ["abcb"]
输出:[]
 
提示:
m == board.length
n == board[i].length
1 <= m, n <= 12
board[i][j] 是一个小写英文字母
1 <= words.length <= 3 * 104
1 <= words[i].length <= 10
words[i] 由小写英文字母组成
words 中的所有字符串互不相同

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

在这里插入图片描述

  • 思路
    1、跟单词搜索 I不同的是处理的数据多了,所以不能再用之前的方法简单的为每个单词进行深度搜索然后汇总,会超时
    2、用前缀树tria,先将单词构建成一颗trial树,然后进行处理

  • 代码

package main

import (
	"fmt"
)
//前缀树结构,注意childres是map,这样才能用O(1)时间查找到孩子节点
type Tria struct{
	childres map[string]*Tria
	isWord bool
}

func findWords(board [][]byte, words []string) []string {
	//先构建tria树
	var root = new(Tria)
	rootb := root
	//遍历单词切片
	for _,v := range words {
		//根节点地址另存一份,每个单词在构建tria时都要用
		root = rootb
		//单词字符串,将每个字符串字符填入前缀树中
		for _,v2 := range v {
			if root.childres[string(v2)] == nil {
				tmp := new(Tria)
				if root.childres == nil {
					root.childres = make(map[string]*Tria)
				}
				root.childres[string(v2)] = tmp
			}
			root = root.childres[string(v2)]
		}
		//标记到此为止是个单词
		root.isWord = true
	}

	//开始处理
	var (
		//log保存状态位,true代表已被使用过
		log [12][12]bool
		str string
		//因为单词可能有重复的,所有先存在map中去重,再将map转为切片返回
		res = make([]string,0)
		resM = make(map[string]bool)
	)
	//遍历board,每个符合第一个单词前缀的格子都进行递归处理
	for i:=0; i<len(board); i++ {
		for j:=0; j<len(board[0]); j++ {
			if  rootb.childres[string(board[i][j])] != nil {
				DFS(&board,rootb,log,i,j,str,&resM)
			}
		}
	}
	//转为题目要求的切片类型
	for k,v := range resM {
		if v == true {
			res = append(res,k)
		}
	}
	return res
}

//深度优先遍历,log是标志位,true代表已被使用过,rowI和colI是行列下标,str是前缀字符串,resM保存符合要求的单词
func DFS(board *[][]byte, root *Tria, log [12][12]bool, rowI int,colI int,str string,resM *map[string]bool) {

	var (
		row = len(*board)
		col = len((*board)[0])
	)
	//递归终止条件,下标越界或已被使用过,不符合要求,终止递归
	if colI >= col || colI < 0 || rowI >= row || rowI < 0 || log[rowI][colI] == true {
		return
	}
	//当前节点不存在该字符,不符合要求,终止递归
	if root.childres[string((*board)[rowI][colI])] == nil {
		return
	}
	//符合要求,将前缀树字符转为字符串Word
	str += string((*board)[rowI][colI])
	//通过标志位isWord判断是否为单词,若是则保存到resM中
	if root.childres[string((*board)[rowI][colI])].isWord == true {
		(*resM)[str] = true
	}
	//将该位置标为已被使用过
	log[rowI][colI] = true
	//依次处理当前位置的上下左右位置
	DFS(board,root.childres[string((*board)[rowI][colI])],log,rowI+1,colI,str,resM)
	DFS(board,root.childres[string((*board)[rowI][colI])],log,rowI-1,colI,str,resM)
	DFS(board,root.childres[string((*board)[rowI][colI])],log,rowI,colI+1,str,resM)
	DFS(board,root.childres[string((*board)[rowI][colI])],log,rowI,colI-1,str,resM)
}


func main() {
	var tmp  = []byte{'o','a','b','n'}
	var t [][]byte
	t = append(t,tmp)

	tmp  = []byte{'o','t','a','e'}
	t = append(t,tmp)
	tmp  = []byte{'a','h','k','r'}
	t = append(t,tmp)

	tmp  = []byte{'a','f','l','v'}
	t = append(t,tmp)

	words := []string{"oa","oaa","ot","ah"}
	res := findWords(t,words)
	fmt.Println(res)
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值