【墨鳌】【力扣 208. 实现 Trie (前缀树)】【数据结构】【HashSet + HashMap + Trie树】

题目描述

实现一颗字典树

跳转链接

Jump To Problem
Jump To Solution

代码

import java.util.ArrayList;
import java.util.Iterator;
class HASet<K> implements Iterable<K> {

    @Override
    public Iterator<K> iterator() {
        return new HASetIterator();
    }

    private class HASetIterator implements Iterator<K> {
        private int index;
        private ArrayList<K> keys;

        public HASetIterator() {
            index = 0;
            keys = new ArrayList<>();
            for (ArrayList<K> bucket : buckets) {
                for (K key : bucket)
                    keys.add(key);
            }
        }

        @Override
        public boolean hasNext() {
            return index < numEntries;
        }

        @Override
        public K next() {
            return keys.get(index++);
        }
    }

    private static final int DEFAULT_CAPACITY = 16;
    private static final double DEFAULT_LOAD_FACTOR = 1.5;

    private ArrayList<ArrayList<K>> buckets;
    private int numBuckets;
    private int numEntries;
    private final double loadFactor;

    public int size() {
        return numEntries;
    }

    public int getNumBuckets() {
        return numBuckets;
    }

    private int hash(K key) {
        int h = key.hashCode() & Integer.MAX_VALUE;
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
    }

    private int hash(K key, int mod) {
        return Math.floorMod(key.hashCode(), mod);
    }

    private void enlarge() {
        ArrayList<ArrayList<K>> newBuckets = new ArrayList<>();
        this.numBuckets *= 2;
        for (int i = 0; i < this.buckets.size() * 2; i++)
            newBuckets.add(new ArrayList<K>());
        for (ArrayList<K> bucket : buckets)
            for (K key : bucket) {
                int index = hash(key, this.numBuckets);
                newBuckets.get(index).add(key);
            }
        this.buckets = newBuckets;
    }

    public HASet(int initialCapacity, double loadFactor) {
        if (initialCapacity < 0) throw new IllegalArgumentException("Illegal initial capacity: " + initialCapacity);
        this.loadFactor = loadFactor;
        this.buckets = new ArrayList<>();
        for (int i = 0; i < initialCapacity; i++)
            this.buckets.add(new ArrayList<K>());
        this.numBuckets = initialCapacity;
        this.numEntries = 0;
    }

    public HASet() {
        this(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR);
    }

    public HASet(int initialCapacity) {
        this(initialCapacity, DEFAULT_LOAD_FACTOR);
    }

    public void clear() {
        for (ArrayList<K> bucket : buckets) bucket.clear();
        this.numEntries = 0;
    }

    public boolean contains(K key) {
        int index=hash(key, numBuckets);
        for(K k: buckets.get(index))
            if(key.equals(k)){
                return true;
            }
        return false;        
    }

    public void add(K key) {
        if (key == null) return;
        if (((double) this.numEntries / (double) this.numBuckets) >= this.loadFactor) enlarge();        
        if (contains(key)) {
            return;
        }
        int index = hash(key, numBuckets);
        this.buckets.get(index).add(key);
        this.numEntries++;
    }

    public K remove(K key) {
        if (key == null) return null;
        if (!contains(key)) return null;
        int index = hash(key, numBuckets);
        K removed = null;
        for (K k: buckets.get(index))
            if (key.equals(k)) {
                removed = k;
            }
        if (removed != null) {
            this.buckets.get(index).remove(removed);
            this.numEntries--;
            return removed;
        }
        return null;
    }
}

/**
 * Hash-based Map
 */
class HAMap<K, V> implements Iterable<K> {

    /**
     * Represents a key-value pair.
     */
    private class Entry {
        K key;
        V value;

        Entry(K k, V v) {
            key = k;
            value = v;
        }
    }

    private static final int DEFAULT_CAPACITY = 16;
    private static final double DEFAULT_LOAD_FACTOR = 1.5;

    private ArrayList<ArrayList<Entry>> buckets;
    private HASet<K> keySet;
    private int numBuckets;
    private int numEntries;
    private final double loadFactor;

    /**
     * @return a set of the keys contained in this map.
     */
    public HASet<K> keySet() {
        return keySet;
    }

    /**
     * @return the number of entries in this map.
     */
    public int size() {
        return numEntries;
    }

    /**
     * @return the number of buckets in this map.
     */
    public int getNumBuckets() {
        return numBuckets;
    }

    /*
     ***************************
     * DO NOT MODIFY CODE ABOVE
     ***************************
     */

    /*
     ***** HELPER METHODS START *****
     */

    private int hash(K key) {
        int h = key.hashCode() & Integer.MAX_VALUE;
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
    }

    private int hash(K key, int mod) {
        return Math.floorMod(key.hashCode(), mod);
        // return Math.floorMod(hash(key), mod);
    }

    private void enlarge() {
        ArrayList<ArrayList<Entry>> newBuckets = new ArrayList<>();
        this.numBuckets *= 2;
        for (int i = 0; i < this.buckets.size() * 2; i++)
            newBuckets.add(new ArrayList<Entry>());
        for (ArrayList<Entry> bucket : buckets)
            for (Entry entry : bucket) {
                int index = hash(entry.key, this.numBuckets);
                newBuckets.get(index).add(entry);
            }
        this.buckets = newBuckets;
    }

    /*
     ***** HELPER METHODS END *****
     */


    // LAB EXERCISE 12.2 CONSTRUCTORS

    public HAMap(int initialCapacity, double loadFactor) {
        if (initialCapacity < 0) throw new IllegalArgumentException("Illegal initial capacity: " + initialCapacity);
        this.loadFactor = loadFactor;
        this.keySet = new HASet<>();
        this.buckets = new ArrayList<>();
        for (int i = 0; i < initialCapacity; i++)
            this.buckets.add(new ArrayList<Entry>());
        this.numBuckets = initialCapacity;
        this.numEntries = 0;
    }

    public HAMap() {
        this(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR);
    }

    public HAMap(int initialCapacity) {
        this(initialCapacity, DEFAULT_LOAD_FACTOR);
    }


    // LAB EXERCISE 12.3 CLEAR

    /**
     * Removes all of the entries from this map.
     */
    public void clear() {
        for (ArrayList<Entry> bucket : buckets) bucket.clear();
        this.keySet.clear();
        this.numEntries = 0;
    }


    // LAB EXERCISE 12.4 CONTAINS KEY and ITERATOR

    /**
     * @param key to be checked
     * @return true iff this map contains an entry with the specified key
     */
    public boolean containsKey(K key) {
        return this.keySet.contains(key);
    }

    /**
     * @return an Iterator that iterates over the stored keys
     */
    @Override
    public Iterator<K> iterator() {
        return this.keySet.iterator();
    }

    // CODING ASSIGNMENT 12.1 GET

    /**
     * @param key of the value to be returned
     * @return the value to which the specified key is mapped
     * null if this map contains no entries of the key
     */
    public V get(K key) {
        if (!containsKey(key)) return null;
        int index = hash(key, this.numBuckets);
        for (Entry entry : buckets.get(index))
            if (entry.key.equals(key)) return entry.value;
        return null;
    }

    // CODING ASSIGNMENT 12.2 PUT

    /**
     * Associates the specified value with the specified key in this map.
     * If the map previously contained an entry with that key, the old value is replaced.
     * The key is not null.
     *
     * @param key   of the entry to be added
     * @param value of the entry to be added
     */
    public void put(K key, V value) {
        if (key == null) return;
        if (((double) this.numEntries / (double) this.numBuckets) >= this.loadFactor) enlarge();
        int index = hash(key, numBuckets);
        if (containsKey(key)) {
            /* replace the old value */
            for (Entry entry : buckets.get(index))
                if (entry.key.equals(key))
                    entry.value = value;
            return;
        }
        this.buckets.get(index).add(new Entry(key, value));
        this.keySet.add(key);
        this.numEntries++;
    }


    // CODING ASSIGNMENT 12.3 REMOVE

    /**
     * Removes the entry for the specified key only if it is
     * currently mapped to the specified value.
     *
     * @param key   of the entry to be removed
     * @param value of the entry to be removed
     * @return the value if entry found,
     * null otherwise
     */
    public V remove(K key, V value) {
        if (key == null) return null;
        if (!containsKey(key)) return null;
        int index = hash(key, numBuckets);
        Entry removed = null;
        for (Entry entry : buckets.get(index))
            if (key.equals(entry.key) && value.equals(entry.value)) {
                removed = entry;
            }
        if (removed != null) {
            this.buckets.get(index).remove(removed);
            this.numEntries--;
            this.keySet.remove(key);
            return removed.value;
        }
        return null;
    }

}


class Trie {

    private HAMap<Character,Trie> children;
    private boolean isWord;

    /** Initialize your data structure here. */
    public Trie() {
        children = new HAMap<>();
        isWord = false;
    }

    /** Inserts a word into the trie. */
    public void insert(String word) {
        Trie node = this;//node先指向根节点
        for(int i = 0; i < word.length(); i++){
            char c =  word.charAt(i);
            if(!node.children.containsKey(c)){
                node.children.put(c,new Trie());
            }
            node = node.children.get(c);
        }
        node.isWord = true;
    }

    /** Returns if the word is in the trie. */
    public boolean search(String word) {
        Trie find = this;
        for(int i = 0; i < word.length(); i++){
            char c = word.charAt(i);
            if(find.children.containsKey(c)){
                find = find.children.get(c);
            }else{
               return false;
            }
        }
        if(find.isWord == true){
            return true;
        }else{
            return false;
        }
    }

    /** Returns if there is any word in the trie that starts with the given prefix. */
    public boolean startsWith(String prefix) {
        Trie cur = this;
        for(int i = 0; i < prefix.length(); i++){
            char c = prefix.charAt(i);
            if(!cur.children.containsKey(c)){
                return false;
            }
            cur = cur.children.get(c);
        }
        return true;
    }

}
posted @ 2022-05-10 23:22  墨鳌  阅读(28)  评论(0编辑  收藏  举报