算法打卡第11周

leetcode第208题实现前缀树

class Trie {

   private TrieNode root;

    private static class TrieNode {
        boolean isEnd;

        TrieNode[] children;

        public TrieNode() {
            this.children = new TrieNode[26];
            this.isEnd = false;
        }
    }


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

    }

    /**
     * Inserts a word into the trie.
     */
    public void insert(String word) {
        if (word == null || word.length() == 0) {
            return;
        }
        TrieNode tmpRoot = root;
        int curson = 0;
        while (true) {
            boolean isContain = containsChar(tmpRoot, word.charAt(curson));
            //前缀树中包含当前字符
            if (!isContain) {
                //将剩余的字符串中的字符插入到前缀树中
                insertTheOtherTrieNode(tmpRoot, word, curson);
                break;
            } else {
                tmpRoot = searhNodeByCh(tmpRoot, word.charAt(curson));
            }
            curson++;
            if (curson > word.length() - 1) {
                tmpRoot.isEnd = true;
                break;
            }
        }
    }

    /**
     * Returns if the word is in the trie.
     */
    public boolean search(String word) {
        if (word == null || word.length() == 0) {
            return false;
        }
        TrieNode tmpRoot = root;
        for (int i = 0; i < word.length(); i++) {
            TrieNode child = searhNodeByCh(tmpRoot, word.charAt(i));
            if (child == null) {
                return false;
            }
            tmpRoot = child;
        }
        return tmpRoot.isEnd ? true : false;

    }

    /**
     * Returns if there is any word in the trie that starts with the given prefix.
     */
    public boolean startsWith(String prefix) {
        if (prefix == null || prefix.length() == 0) {
            return false;
        }
        TrieNode tmpRoot = root;
        for (int i = 0; i < prefix.length(); i++) {
            TrieNode child = searhNodeByCh(tmpRoot, prefix.charAt(i));
            if (child == null) {
                return false;
            }
            tmpRoot = child;
        }
        return true;
    }

    //判断当前节点的子节点是否包含这个字符
    private boolean containsChar(TrieNode parent, char ch) {
        return searhNodeByCh(parent, ch) != null;
    }

    private int calPos(char ch) {
        return Integer.valueOf(ch) - Integer.valueOf('a');
    }

    private TrieNode searhNodeByCh(TrieNode parent, char ch) {
        TrieNode[] children = parent.children;
        int pos = calPos(ch);
        return children[pos];
    }

    private TrieNode insertTrieNode(TrieNode parent, char ch) {
        TrieNode[] children = parent.children;
        int pos = calPos(ch);
        TrieNode node = new TrieNode();
        children[pos] = node;
        return node;
    }


    private void insertTheOtherTrieNode(TrieNode parent, String word, int startIndex) {
        while (true) {
            TrieNode trieNode = insertTrieNode(parent, word.charAt(startIndex));
            parent = trieNode;
            startIndex++;
            if (startIndex > word.length() - 1) {
                trieNode.isEnd = true;
                break;
            }
        }
    }
}

初始化前缀树的时间复杂度是O(m*n),m为字符串的个数,n为插入的字符串的数据规模。查询是否包含某个字符串的时间复杂度为O(logn)。

leetcode第2097题多次搜索
给定一个较长字符串big和一个包含较短字符串的数组smalls,设计一个方法,根据smalls中的每一个较短字符串,对big进行搜索。输出smalls中的字符串在big里出现的所有位置positions,其中positions[i]为smalls[i]出现的所有位置。

class Solution {
      private Trie trie;

    public Solution() {
        this.trie = new Trie();

    }

    public int[][] multiSearch(String big, String[] smalls) {
         if (smalls == null || smalls.length == 0 ) {
            return new int[0][0];
        }
        if (big== null || big.length() == 0) {
            return new int[smalls.length][0];
        }
        int[][] result = new int[smalls.length][];
        List<Integer> recordList = new ArrayList<>();
        //使用smalls构建前缀树
        for (int i = 0; i < smalls.length; i++) {
            trie.insert(smalls[i], i);
            recordList.add(i);
        }
        Map<Integer, List<Integer>> tmpResultMap = new HashMap<>();
        for (int i = 0; i < big.length(); i++) {
            List<Trie.TrieNode> trieNodes = trie.search(i, big, trie.root);
            List<Integer> indexList = new ArrayList<>();
            for (Trie.TrieNode node : trieNodes) {
                indexList.add(node.arrIndex);
            }
            tmpResultMap.put(i, indexList);
        }
        Map<Integer, List<Integer>> resultMap = new HashMap<>();
        //整理
        for (Map.Entry<Integer, List<Integer>> entry : tmpResultMap.entrySet()) {
            Integer key = entry.getKey();
            List<Integer> values = entry.getValue();
            for (Integer value : values) {
                if (resultMap.get(value) == null) {
                    List<Integer> keyList = new ArrayList<>();
                    keyList.add(key);
                    resultMap.put(value, keyList);
                } else {
                    resultMap.get(value).add(key);
                }
            }
        }
        for (Map.Entry<Integer, List<Integer>> entry : resultMap.entrySet()) {
            Integer key = entry.getKey();
            List<Integer> values = entry.getValue();
            result[key] = new int[values.size()];
            for (int i = 0; i < values.size(); i++) {
                result[key][i] = values.get(i);
            }
            recordList.remove(key);
        }
        for (Integer record : recordList) {
            result[record] = new int[0];
        }

        return result;

    }

    public static class Trie {

        private TrieNode root;

        public static class TrieNode {
            private Integer arrIndex;
            private boolean isEnd;
            private TrieNode[] children;

            public TrieNode() {
                this.children = new TrieNode[26];
            }
        }

        public Trie() {
            this.root = new TrieNode();
        }

        public void insert(String word, int arrIndex) {
            if (word == null || word.length() == 0) {
                return;
            }
            TrieNode tmpRoot = root;
            int curson = 0;
            while (true) {
                boolean isContain = containsChar(tmpRoot, word.charAt(curson));
                //前缀树中包含当前字符
                if (!isContain) {
                    //将剩余的字符串中的字符插入到前缀树中
                    insertTheOtherTrieNode(tmpRoot, word, curson, arrIndex);
                    break;
                } else {
                    tmpRoot = searhNodeByCh(tmpRoot, word.charAt(curson));
                }
                curson++;
                if (curson > word.length() - 1) {
                    tmpRoot.arrIndex = arrIndex;
                    tmpRoot.isEnd = true;
                    break;
                }
            }
        }

        public List<TrieNode> search(int index, String word, TrieNode tmpRoot) {
            if (word == null || word.length() == 0) {
                return null;
            }
            List<TrieNode> trieNodes = new ArrayList<>();

            while (index < word.length()) {
                TrieNode trieNode = searhNodeByCh(tmpRoot, word.charAt(index));
                if (trieNode != null && trieNode.arrIndex != null) {
                    trieNodes.add(trieNode);
                }
                if (trieNode == null) {
                    break;
                }
                tmpRoot = trieNode;
                index++;
            }
            return trieNodes;
        }


        //判断当前节点的子节点是否包含这个字符
        private boolean containsChar(TrieNode parent, char ch) {
            return searhNodeByCh(parent, ch) != null;
        }

        private int calPos(char ch) {
            return Integer.valueOf(ch) - Integer.valueOf('a');
        }

        private TrieNode searhNodeByCh(TrieNode parent, char ch) {
            TrieNode[] children = parent.children;
            int pos = calPos(ch);
            return children[pos];
        }

        private TrieNode insertTrieNode(TrieNode parent, char ch) {
            TrieNode[] children = parent.children;
            int pos = calPos(ch);
            TrieNode node = new TrieNode();
            children[pos] = node;
            return node;
        }


        private void insertTheOtherTrieNode(TrieNode parent, String word, int startIndex, int arrIndex) {
            while (true) {
                TrieNode trieNode = insertTrieNode(parent, word.charAt(startIndex));
                parent = trieNode;
                startIndex++;
                if (startIndex > word.length() - 1) {
                    trieNode.arrIndex = arrIndex;
                    trieNode.isEnd = true;
                    break;
                }
            }
        }
     }
}

查询的时间复杂度为O(m*logn),m为大字符串的长度,n为小字符串数组某一字符串的长度。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值