LeetCode 212:单词搜索|| ——C#实现

这篇博客介绍了如何用C#解决LeetCode上的212题——单词搜索。通过解释示例和提供解题思路,讨论了如何优化回溯算法以处理大规模数据,并探讨了利用前缀树进行早期回溯的可能性。作者分享了从其他博客中学习到的两种解题方法,并提供了自己的C#代码实现。

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

题目:

给定一个二维网格 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(前缀树)

 虽然之前做过前缀树的题目,但是还是不知道具体该怎么实现,百度了两个解法,阅读后给出自己的答案:

两个解法:https://blog.youkuaiyun.com/Viscu/article/details/82470435

https://blog.youkuaiyun.com/liujunzxcv/article/details/79849665

C#代码:

public class Trie
    {
        private class Node
        {
            public Node[] children;
            public bool isEnd = false;
            public Node()
            {
                children = new Node[26];
                isEnd = false;
            }
        }

        private Node rootNode = null;
        /** Initialize your data structure here. */
        public Trie()
        {
            rootNode = new Node();
        }

        /** Inserts a word into the trie. */
        public void Insert(String word)
        {
            Node currNode = rootNode;
            for (int i = 0; i < word.Length; i++)
            {
                if (currNode.children[word[i] - 'a'] == null)
                {
                    currNode.children[word[i] - 'a'] = new Node();
                }
                currNode = currNode.children[word[i] - 'a'];
            }
            currNode.isEnd = true;                    
        }

        /** Returns if the word is in the trie. */
        public bool Search(String word)
        {
            Node currNode = rootNode;
            for (int i = 0; i < word.Length; i++)
            {
                if (currNode.children[word[i] - 'a'] == null)
                {
                    return false;
                }
                currNode = currNode.children[word[i] - 'a'];
            }
            return currNode.isEnd;          
        }

        /** Returns if there is any word in the trie that starts with the given prefix. */
        public bool StartsWith(String prefix)
        {
            Node currNode = rootNode;
            for (int i = 0; i < prefix.Length; i++)
            {
                if (currNode.children[prefix[i] - 'a'] == null)
                {
                    return false;
                }
                currNode = currNode.children[prefix[i] - 'a'];
            }
            return true;
        }
    }

    public class Solution
    {
        public int[] dx = { 1, -1, 0, 0 };
        public int[] dy = { 0, 0, 1, -1 };
        public List<string> res = new List<string>();
        public bool[][] vis;

        public IList<string> FindWords(char[][] board, string[] words)
        {
            int n = words.Length;
            int rn = board.Length;
            int cn = board[0].Length;
            if (rn > 0 && cn > 0 && n > 0)
            {
                Trie trie = new Trie();
                foreach (string word in words)
                {
                    trie.Insert(word);
                }

                vis = new bool[rn][];
                for (int i = 0; i < rn; i++)
                {
                    vis[i] = new bool[cn];
                }

                for (int i = 0; i < rn; i++)
                {
                    for (int j = 0; j < cn; j++)
                    {
                        Dfs(trie, i, j, board, "");
                    }
                }
            }
            res.Sort();
            return res;
        }

        public void Dfs(Trie trie, int x, int y, char[][] board, string curStr)
        {
            int rn = board.Length;
            int cn = board[0].Length;
            if (x < 0 || y < 0 || x >= rn || y >= cn || vis[x][y])
            {
                return;
            }

            curStr = curStr + board[x][y];           
            if (trie.Search(curStr))
            {
                if (!res.Contains(curStr))
                {
                    res.Add(curStr);
                }
            }
            if (trie.StartsWith(curStr))
            {
                vis[x][y] = true;
                for (int i = 0; i < 4; i++)
                {
                    Dfs(trie, x + dx[i], y + dy[i], board, curStr);                  
                }
            }
            vis[x][y] = false;
        }
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值