LeetCode-in-Java

2452. Words Within Two Edits of Dictionary

Medium

You are given two string arrays, queries and dictionary. All words in each array comprise of lowercase English letters and have the same length.

In one edit you can take a word from queries, and change any letter in it to any other letter. Find all words from queries that, after a maximum of two edits, equal some word from dictionary.

Return a list of all words from queries, that match with some word from dictionary after a maximum of two edits. Return the words in the same order they appear in queries.

Example 1:

Input: queries = [“word”,”note”,”ants”,”wood”], dictionary = [“wood”,”joke”,”moat”]

Output: [“word”,”note”,”wood”]

Explanation:

Thus, we return [“word”,”note”,”wood”].

Example 2:

Input: queries = [“yes”], dictionary = [“not”]

Output: []

Explanation:

Applying any two edits to “yes” cannot make it equal to “not”. Thus, we return an empty array.

Constraints:

Solution

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class Solution {
    private Node root;

    static class Node {
        HashMap<Character, Node> childs = new HashMap<>();
    }

    private void insert(String s) {
        Node curr = root;
        for (char ch : s.toCharArray()) {
            if (curr.childs.get(ch) == null) {
                curr.childs.put(ch, new Node());
            }
            curr = curr.childs.get(ch);
        }
    }

    private boolean search(String word, Node curr, int i, int edits) {
        // if reached the end with less than or equal 2 edits then return truem
        if (i == word.length()) {
            return edits <= 2;
        }
        // more than 2 mismatch don't go further
        if (edits > 2) {
            return false;
        }
        // there might be a case start is matching but others are diff and that's a edge case to
        // handle
        boolean ans = false;
        for (Character ch : curr.childs.keySet()) {
            ans |=
                    search(
                            word,
                            curr.childs.get(ch),
                            i + 1,
                            ch == word.charAt(i) ? edits : edits + 1);
        }
        return ans;
    }

    public List<String> twoEditWords(String[] queries, String[] dictionary) {
        root = new Node();
        for (String s : dictionary) {
            insert(s);
        }
        List<String> ans = new ArrayList<>();
        for (String s : queries) {
            boolean found = search(s, root, 0, 0);
            if (found) {
                ans.add(s);
            }
        }
        return ans;
    }
}