如何让我的trie更有效率?

时间:2016-01-30 19:02:11

标签: c# data-structures trie

我正在研究黑客等级问题,我相信我的解决方案是正确的。但是,我的大部分测试用例都已超时。有人可以建议如何提高我的代码效率吗?

代码的重要部分始于“Trie Class”。

确切的问题可以在这里找到:https://www.hackerrank.com/challenges/contacts

using System;
using System.Collections.Generic;
using System.IO;
class Solution
{
    static void Main(String[] args)
    {
        int N = Int32.Parse(Console.ReadLine());
        string[,] argList = new string[N, 2];
        for (int i = 0; i < N; i++)
        {
            string[] s = Console.ReadLine().Split();
            argList[i, 0] = s[0];
            argList[i, 1] = s[1];
        }

        Trie trie = new Trie();

        for (int i = 0; i < N; i++)
        {
            switch (argList[i, 0])
            {
                case "add":
                    trie.add(argList[i, 1]);
                    break;
                case "find":
                    Console.WriteLine(trie.find(argList[i, 1]));
                    break;
                default:
                    break;
            }
        }
    }
}

class Trie
{
    Trie[] trieArray = new Trie[26];
    private int findCount = 0;
    private bool data = false;
    private char name;

    public void add(string s)
    {
        s = s.ToLower();
        add(s, this);
    }

    private void add(string s, Trie t)
    {
        char first = Char.Parse(s.Substring(0, 1));
        int index = first - 'a';

        if(t.trieArray[index] == null)
        {
            t.trieArray[index] = new Trie();
            t.trieArray[index].name = first;
        }

        if (s.Length > 1)
        {
            add(s.Substring(1), t.trieArray[index]);
        }
        else
        {
            t.trieArray[index].data = true;
        }
    }

    public int find(string s)
    {
        int ans;
        s = s.ToLower();
        find(s, this);

        ans = findCount;
        findCount = 0;
        return ans;
    }

    private void find(string s, Trie t)
    {
        if (t == null)
        {
            return;
        }
        if (s.Length > 0)
        {
            char first = Char.Parse(s.Substring(0, 1));
            int index = first - 'a';
            find(s.Substring(1), t.trieArray[index]);
        }
        else
        {
            for(int i = 0; i < 26; i++)
            {
                if (t.trieArray[i] != null)
                {
                    find("", t.trieArray[i]);
                }
            }

            if (t.data == true)
            {
                findCount++;
            }
        }
    }

}

编辑:我在评论中做了一些建议,但意识到我不能用s [0]替换s.Substring(1)...因为我实际上需要s [1 .. N]。 AND s [0]返回一个char,所以我还是需要做.ToString就可以了。

另外,要添加更多信息。这个想法是它需要在前缀之后计算所有名称。例如。

Input: "He"
Trie Contains:
"Hello"
"Help"
"Heart"
"Ha"
"No"
Output: 3

2 个答案:

答案 0 :(得分:2)

我可以在这里发布一个解决方案,给你40分,但我想这不会有任何乐趣。

  • 使用Enumerator&lt; char&gt;而不是任何字符串操作
  • 添加值时计数
  • 任何charachter减去'a'会产生一个好的arrayindex(给你0到25之间的值)

enter image description here

答案 1 :(得分:1)

我认为,this link必须非常有帮助

在那里,您可以找到trie数据结构的良好实现,但它是一个java实现。一年前我在c#上使用那篇伟大的文章实现了trie,我试图找到另一个hackerrank任务的解决方案。它很成功。

enter image description here

在我的任务中,我只需要一个简单的trie(我的意思是我的字母表等于2)并且只有一种添加新节点的方法:

public class Trie
{
   //for integer representation in binary system 2^32
    public static readonly int MaxLengthOfBits = 32;
    //alphabet trie size
    public static readonly int N = 2;

    class Node
    {
        public Node[] next = new Node[Trie.N];
    }

    private Node _root;
}

public void AddValue(bool[] binaryNumber)
{
    _root = AddValue(_root, binaryNumber, 0);
}

private Node AddValue(Node node, bool[] val, int d)
{
    if (node == null) node = new Node();

    //if least sagnificient bit has been added
    //need return
    if (d == val.Length)
    {   
        return node;
    }

    // get 0 or 1 index of next array(length 2)
    int index = Convert.ToInt32(val[d]); 
    node.next[index] = AddValue(node.next[index], val, ++d);
    return node;
}