栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

剑指 Offer II 109. 开密码锁-BFS-Java

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

剑指 Offer II 109. 开密码锁-BFS-Java

1.题目

 

2.思路

一开始想着能不能先使用DFS,快速写出来,然后再使用BFS来写,因为一般DFS写代码的时间短一点,BFS 需要自己构建队列,时间会长一点。

然后DFS超时了,因为DFS侧重于遍历从起点到最深的节点,相当于这里会遍历无数个没用的节点。时间复杂度应该是O(10 ^ 4 * 10 ^ 4),所以只能用BFS来判断。

对于BFS来说,每一次遍历都是一层,相当于是走一步,这样总会有x层的时候,走到target,找到答案,或者结束。

这道题的两个要点:

  • 如何求解一个字符串的下一个字符串?比如一开始为“0000”,下一个字符串有哪些?
  • 注意边界条件剪枝,比如记录是否访问过vis, 是不是出现在死亡数组里面。
第一个问题求解一个字符串的下一个字符串?

首先就是有四个字符可以进行+ 1 和 -1 两个操作,所以相当于有8个候选字符串。每次从中选一个假如队列即可。中间会有一些已经访问过的,所以记得去重剪枝,不然会超时。

注意字符串数组char[]arr转化为String的话,不要用arr.toString(),因为这样得到的是字符串的地址。需要使用new String(arr)

可以使用一个函数来计算下一个字符串的集合。这样代码功能区分更明显。

第二个问题剪枝
  • 一开始用一个map存一下死亡数组,这样可以O(1)时间判断是否出现在死亡数组中。
  • 用一个visMap记录这个字符串是否已经访问过,剪枝
  • 最开始判断target是否出现在死亡数组里面,如果出现,直接return -1
  • 找到结果,return step
时间复杂度——O(10^4 * (8 + 8) +  4 * m)

首先,从“0000”  -- “9999”总共有10 ^ 4个字符串(状态空间的上限)。然后计算每个字符串的下一个字符为O(8), 加入队列也有O(8),然后还有计算思死亡数组的O(4 * m),大概是这样。

空间复杂度——O(10^4 * 8 + m + 1)

首先死亡数组的哈希表空间O(m), 然后队列中存的元素最大个数为10^ 4 , 每个字符串长度为4,还有一个step 1, 为O(10 * 4 + 5),大概是这样。

class Solution {
    int ans = 0;
    Mapmap = new HashMap();
    MapvisMap = new HashMap();
    public int openLock(String[] deadends, String target) {
        for(String s : deadends){
            map.put(s, 1);
        }
        if(map.containsKey(target))return -1;
        Dequed = new ArrayDeque<>();
        d.addLast(new String[]{"0000", "0"});
        while(!d.isEmpty()){
            String[]cur = d.pollFirst();
            String start = cur[0];
            int step = Integer.parseInt(cur[1]);
            if(map.containsKey(start))continue;
            if(visMap.containsKey(start))continue; //已经访问过
            if(start.equals(target)){  //找到答案
                return step;
            }
            visMap.put(start, 1);
            Listlist = getNextString(start);
            for(String s : list){
                if(!map.containsKey(s) && !visMap.containsKey(s)){
                    d.addLast(new String[]{s, step + 1 +""});
                }
            }

        }
        return -1;
    }
    public List getNextString(String s){
        char[]arrays = s.toCharArray();
        int[]dx = new int[]{1, -1};
        Listlist = new ArrayList();
        for(int i = 0 ; i < 4; i++){
            for(int j = 0 ; j < 2; j++){
                char tempCopy = arrays[i];
                int temp = (int)(arrays[i] - '0') + dx[j];
                if(temp == -1){
                    arrays[i] = '9';
                }
                else if(temp == 10){
                    arrays[i] = '0';
                }
                else{
                    arrays[i] = (char)(temp + '0');
                }
                list.add(new String(arrays));
                // list.add(arrays.toString()); //不能这样将字符数组转化为字符串。这样输出的是字符串的地址。
                arrays[i] = tempCopy;
            }
        }
        return list;
    }
}
3.结果

如果用Set存储,应该时间还会再少一些。 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/820132.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号