676. 实现一个魔法字典 / 剑指 Offer II 111. 计算除法

676. 实现一个魔法字典【中等题】【每日一题】

思路:【暴力寻找】

就是用暴力碰碰运气,实在是对字典树有点怵,比较逃避。
结果跟官解方法1的代码思路完全一致~

也不用设计特殊的数据结构,就用传入的数组即可。
遍历数组中每一个单词,将其与传入单词进行比较,如果确实只相差一个字母,那么说明搜索成功,返回true,如果数组中所有单词都比较了一遍都没有只差一个字母的单词,那么说明搜索失败,返回false。

代码:

class MagicDictionary {

    String[] dict;

    public MagicDictionary() {

    }
    
    public void buildDict(String[] dictionary) {
        this.dict = dictionary;
    }
    
    public boolean search(String searchWord) {
        for(String target : dict){
            if(makeSure(searchWord,target)){
                return true;
            }
        }
        return false;
    }

    public boolean makeSure(String word,String target){
        if(word.length() != target.length()){
            return false;
        }else{
            int n = word.length(),cnt = 0;
            for(int i = 0; i < n ; i++){
                if(word.charAt(i) != target.charAt(i)){
                    cnt++;
                }
            }
            return cnt == 1;
        }
    }
}

/**
 * Your MagicDictionary object will be instantiated and called as such:
 * MagicDictionary obj = new MagicDictionary();
 * obj.buildDict(dictionary);
 * boolean param_2 = obj.search(searchWord);
 */

剑指 Offer II 111. 计算除法【中等题】

思路:

对官解的方法一,建图+BFS做了详细注解。

代码:

class Solution {
    public double[] calcEquation(List<List<String>> equations, double[] values, List<List<String>> queries) {
        //记录变量个数
        int v_num = 0;
        Map<String,Integer> variables = new HashMap<>();
        //记录等式个数
        int n = equations.size();

        //建表,将每个变量放入哈希表中,并以数字进行标记
        for (List<String> equation : equations) {
            String v1 = equation.get(0), v2 = equation.get(1);
            if (!variables.containsKey(v1)) {
                variables.put(v1, v_num++);
            }
            if (!variables.containsKey(v2)) {
                variables.put(v2, v_num++);
            }
        }

        //建图,对于每个点,存储其直接连接到的所有点及对应的权值
        //权值表示的含义为: 比如说 a/b = 2.0 ,那么a的直接连接点为b,对应权值为2.0,b的直接连接点为a,对应权值为 1/2.0
        List<Pair>[] edges = new List[v_num];
        for (int i = 0; i < v_num; i++) {
            edges[i] = new ArrayList<>();
        }
        for (int i = 0; i < n; i++) {
            int v1 = variables.get(equations.get(i).get(0)),v2 = variables.get(equations.get(i).get(1));
            edges[v1].add(new Pair(v2,values[i]));
            edges[v2].add(new Pair(v1,1.0 / values[i]));
        }

        //尝试求出每条查询的答案
        //记录查询个数
        int query_num = queries.size();
        //定义答案数组 用来存储每条查询的答案
        double[] ans = new double[query_num];
        //遍历每一条查询
        for (int i = 0; i < query_num; i++) {
            //得到当前查询为 query
            List<String> query = queries.get(i);
            //定义当前查询的结果为 result 默认值为 -1.0
            double result = -1.0;
            //记录当前查询第一个变量(被除数)q1,记录当前查询第二个变量(除数)q2
            String q1 = query.get(0),q2 = query.get(1);
            //只有变量表中同时存在q1和q2,当前查询才有答案,若不满足这个条件,则当前查询的答案即为默认值 -1.0
            if (variables.containsKey(q1) && variables.containsKey(q2)){
                //变量表中同时存在q1和q2,则求出答案
                //记录q1的数字节点值为i1,q2的数字节点值为i2
                int i1 = variables.get(q1),i2 = variables.get(q2);
                //如果 i1 == i2 ,说明q1和q2变量相等,则答案为 1.0
                if (i1 == i2){
                    result = 1.0;
                }else {
                    //如果q1和q2变量不相等,则开启BFS搜索
                    //定义 节点队列 points,队列中的节点均与i1节点有连接
                    Queue<Integer> points = new LinkedList<>();
                    //将q1变量的节点值加入队列
                    points.offer(i1);
                    //定义暂存结果数组 ratios,用来存放 q1 / 其他变量 的值,那么当前查询的结果就可以表示为 ratios[i2]
                    double[] ratios = new double[v_num];
                    //ratios赋初值,全部为 -1.0
                    Arrays.fill(ratios,-1.0);
                    // q1 / q1 = 1.0
                    ratios[i1] = 1.0;
                    
                    //当points不为空 且 ratios[i2] < 0 时,说明尚未搜索到i2节点与i1节点建立的连接(即尚未搜索到 q1/q2)
                    while(!points.isEmpty() && ratios[i2] < 0){
                        //拉取队列头部 记为 x
                        int x = points.poll();
                        //遍历所有与 节点x相连的节点及其对应的权值
                        for (Pair pair : edges[x]) {
                            //记录当前与x节点相连的节点为y
                            int y = pair.index;
                            //记录当前与x节点相连的权值为val,即 x = y * val
                            double val = pair.value;
                            //如果ratios[y] < 0,说明y节点尚未与 i1节点建立联系,则尝试将y节点与i1节点建立连接
                            //由于x节点已经与 i1节点建立连接,因此可以通过x将y与i1连接起来
                            if (ratios[y] < 0){
                                //ratios[y] = i1 / y ,而 i1 / x = ratios[x] ,x = y * val
                                //于是 ratios[y] = x * ratios[x] / y = y * val * ratios[x] / y = ratios[x] * val
                                ratios[y] = ratios[x] * val;
                                //此时y节点与i1节点建立连接,将其加入队列
                                points.offer(y);
                            }
                        }
                    }
                    //将当前查询的结果result 赋值为 ratios[i2]
                    result = ratios[i2];
                }
            }
            //将当前查询的答案 ans[i]赋值为 result
            ans[i] = result;
        }
        return ans;
    }
}

class Pair {
    int index;
    double value;

    Pair(int index,double value){
        this.index = index;
        this.value = value;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值