Java剑指 Offer II 109. 开密码锁(击败14.24%用户,没写双向BFS,太累了,效率比较差)

题目:

一个密码锁由 4 个环形拨轮组成,每个拨轮都有 10 个数字: '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' 。每个拨轮可以自由旋转:例如把 '9' 变为 '0','0' 变为 '9' 。每次旋转都只能旋转一个拨轮的一位数字。

锁的初始数字为 '0000' ,一个代表四个拨轮的数字的字符串。

列表 deadends 包含了一组死亡数字,一旦拨轮的数字和列表里的任何一个元素相同,这个锁将会被永久锁定,无法再被旋转。

字符串 target 代表可以解锁的数字,请给出解锁需要的最小旋转次数,如果无论如何不能解锁,返回 -1 。

示例 :

输入:deadends = ["0201","0101","0102","1212","2002"], target = "0202"
输出:6
解释:
可能的移动序列为 "0000" -> "1000" -> "1100" -> "1200" -> "1201" -> "1202" -> "0202"。
注意 "0000" -> "0001" -> "0002" -> "0102" -> "0202" 这样的序列是不能解锁的,因为当拨动到 "0102" 时这个锁就会被锁定。

思路:

广度优先遍历,可以写双向效率会好一点,懒得写了

复杂度:

时间:单循环O( n )。

空间:O( n )。

代码:

 public int openLock(String[] deadends, String target) {
        //dead来存放死锁状态
        Set<String> dead = new HashSet<>(Arrays.asList(deadends));
        //visited 表示访问过的密码 
        Set<String> visited = new HashSet<>();
        //定义初始值
        String init ="0000";
        //死锁里有初始值和目标值都退出
        if(dead.contains(init) || dead.contains(target)){
            return -1;
        }

        Queue<String> queue1 = new LinkedList<>();
        Queue<String> queue2 = new LinkedList<>();
        //初始长度0
        int step = 0;
        //将初始值压入队列
        queue1.offer(init);
        visited.add(init);
        while(!queue1.isEmpty()){
            //拿queue1中的元素比较
            String cur = queue1.remove();
            if(cur.equals(target)){
                return step;
            }

            List<String> nexts = getNeighbors(cur);
            for(String next :nexts){
                if(!dead.contains(next) && !visited.contains(next)){
                    queue2.add(next);
                    visited.add(next);
                }
            }
            if(queue1.isEmpty()){
            step++;
            queue1 = queue2;
            queue2 = new LinkedList<>();
            } 
        }
        return -1;
    }

     //写函数来得到与某个状态相连的八个状态
      private List<String> getNeighbors(String cur){
        List<String> nexts = new LinkedList<>();
        
        for(int i =0;i<cur.length();++i){
            char ch = cur.charAt(i);
       
            char newCh = ch == '0'?'9':(char)(ch-1);
            StringBuilder builder = new StringBuilder(cur);
            builder.setCharAt(i,newCh);
            nexts.add(builder.toString());

            newCh = ch == '9'?'0':(char)(ch+1);
            builder.setCharAt(i,newCh);
            nexts.add(builder.toString());
        }
       
        return nexts;
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值