最长公共前缀和有效括号

其实最长公共前缀这个题目很容易就能想到水平扫描(两两比较,逐渐缩小范围)或者垂直扫描(同时比较所有字符串的同一位),而且性能很好;稍微高级一点的想法大概是分治,但是分治占用的空间有点大,毕竟是基于递归的。据说这种题目的通用解法是前缀树,但是前缀树我没用过,所以记录一下。

C++实现和Java实现还是有点区别的,尤其是在对null的判断上。在Java里可以很轻易地进行类似于object == null这样的判断,但是在C++里就必须用指针。

// 结点
class TrieNode
{
private:
    TrieNode *next[26] = {nullptr};
    bool isEnd;
    // 非空子节点的数量
    int size = 0;

public:
    bool containsKey(char ch)
    {
        return next[ch - 'a'] != nullptr;
    }
    TrieNode *get(char ch)
    {
        return next[ch - 'a'];
    }
    void put(char ch, TrieNode *node)
    {
        next[ch - 'a'] = node;
        ++size;
    }
    void setEnd()
    {
        isEnd = true;
    }
    bool getEnd()
    {
        return isEnd;
    }
    int getLinks()
    {
        return size;
    }
};
// 树
class Trie
{
private:
    TrieNode *root;

    // search a prefix or whole key in trie and
    // returns the node where search ends
    TrieNode *searchPrefix(string &word)
    {
        TrieNode *node = root;
        for (auto c : word)
        {
            if (node->containsKey(c))
            {
                node = node->get(c);
            }
            else
            {
                return nullptr;
            }
        }
        return node;
    }

public:
    /** Initialize your data structure here. */
    Trie()
    {
        root = new TrieNode();
    }

    /** Inserts a word into the trie. */
    void insert(string word)
    {
        TrieNode *node = root;
        for (auto c : word)
        {
            if (!node->containsKey(c))
            {
                node->put(c, new TrieNode());
            }
            node = node->get(c);
        }
        node->setEnd();
    }

    /** Returns if the word is in the trie. */
    bool search(string word)
    {
        TrieNode *node = searchPrefix(word);
        return node != nullptr && node->getEnd();
    }

    /** Returns if there is any word in the trie that starts with the given prefix. */
    bool startsWith(string prefix)
    {
        TrieNode *node = searchPrefix(prefix);
        return node != nullptr;
    }

    string searchLongestPrefix(const string &word)
    {
        TrieNode *node = root;
        string prefix;
        for (auto c : word)
        {
            if (node->containsKey(c) &&
                node->getLinks() == 1 &&
                !node->getEnd())
            {
                prefix += c;
                node = node->get(c);
            }
            else
            {
                return prefix;
            }
        }
        return prefix;
    }
};

至于有效括号,很显然用辅助栈就可以解决。但是在选择上有一些讲究,在这种简单的场景下,我们完全可以用数组自己实现一个栈,这样可以减少空间的占用。

感觉上,在简单的情况下,数组比栈和map快,switch-case比map快;可能这就是减少对外部实体的依赖。

看到一句话,觉得很有道理:栈可以辅助我们进行从外向内的递归。这对于不清楚结构的问题是很有效的。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值