LeetCode#677 Map Sum Pairs (Java Writing)

Keywords: Attribute

stem

Implement two methods in a MapSum class, insert and sum.
For method insert, you will get a pair of key-value pairs (string, integer). Strings represent keys and integers represent values. If the key already exists, the original key-value pair will be replaced by a new key-value pair.
For method sum, you get a string representing the prefix, and you need to return the sum of the values of all keys that begin with that prefix.
Example 1:

Input: insert("apple", 3), output: Null
Input: sum("ap"), output: 3
Input: insert("app", 2), output: Null
Input: sum("ap"), output: 5

solution

1. Create Map to store integer values

This idea is the way I think when I don't understand Trie deeply enough. I mistakenly thought that every node with the same character was the same node. If we use value attribute to assign value to them, it will lead to the value overlap of words such as AB and cb. But in fact, each node is unique, it is only connected with one character node on it and the next character node, and has no connection with other nodes. The following is my misguided solution:

It is easy to think of using Trie to do this. The idea of this method is to preserve the isWord attribute of the node and add a map object to Trie. When Trie adds a new word, it saves the value of the word in the map. Then in sum's function, we use recursive method to continuously query whether the characters with this prefix have isWord markers, or add them together, and add a recursive function containing the next node and a new string (the original prefix plus this character), finally we can get the sum value.

class MapSum {
    private class Node{
        public boolean isWord;
        public TreeMap<Character, Node> next;

        public Node(){
            isWord = false;
            next = new TreeMap<>();
        }
    }
    private Node root;
    private TreeMap<String, Integer> map;
    /** Initialize your data structure here. */
    public MapSum() {
        root = new Node();
        map = new TreeMap<>();
    }

    public void insert(String key, int val) {
        map.put(key,val);
        Node cur = root;
        for(int i = 0;i < key.length(); i ++){
            char c = key.charAt(i);
            if(cur.next.get(c) == null)
                cur.next.put(c, new Node());
            cur = cur.next.get(c);
        }
        cur.isWord = true;
    }

    public int sum(String prefix) {
        Node cur = root;
        int sum = 0;
        for(int i = 0; i< prefix.length(); i++){
            char c = prefix.charAt(i);
            if(cur.next.get(c) == null)
                return 0;
            cur = cur.next.get(c);
        }
        if(cur.isWord)
            sum += map.get(prefix);

        return sum + sum(cur, prefix);
    }
    private int sum(Node node, String str){
        int sum = 0;
        for(char c : node.next.keySet()){
            if (node.next.get(c).isWord) {
                sum = sum + map.get(str + c) + sum(node.next.get(c), str + c);
            } else {
                sum = sum + sum(node.next.get(c), str + c);
            } 
        }
        return sum;
    }
}

2 Use value attributes in Node nodes

Recursive summation is enough.

class MapSum {
    private class Node{
        public int value;
        public HashMap<Character, Node> next;

        public Node(int value){
            this.value = value;
            next = new HashMap<>();
        }
        public Node(){
            this(0);
        }
    }
    private Node root;
    /** Initialize your data structure here. */
    public MapSum() {
        root = new Node();
    }

    public void insert(String key, int val) {
        Node cur = root;
        for(int i = 0;i < key.length(); i ++){
            char c = key.charAt(i);
            if(cur.next.get(c) == null)
                cur.next.put(c, new Node());
            cur = cur.next.get(c);
        }
        cur.value = val;
    }

    public int sum(String prefix) {
        Node cur = root;
        for(int i = 0; i< prefix.length(); i++){
            char c = prefix.charAt(i);
            if(cur.next.get(c) == null)
                return 0;
            cur = cur.next.get(c);
        }
        int sum = cur.value;
        return sum(cur);
    }
    private int sum(Node node){
        int sum = node.value;
        for(char c : node.next.keySet()){
            sum += sum(node.next.get(c));
        }
        return sum;
    }
}

Posted by loureiro on Thu, 19 Sep 2019 00:23:49 -0700