LeetCode Go-打开转盘锁

题目:打开转盘锁
你有一个带有四个圆形拨轮的转盘锁。每个拨轮都有10个数字: ‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’ 。每个拨轮可以自由旋转:例如把 ‘9’ 变为 ‘0’,‘0’ 变为 ‘9’ 。每次旋转都只能旋转一个拨轮的一位数字。

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

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

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

作者:力扣 (LeetCode)
链接:https://leetcode-cn.com/leetbook/read/queue-stack/kj48j/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


Solve:
BFS广度优先搜索、双向BFS均能解答

(2020.12.17)单向BFS会超时

解答要点:

1.以基本的BFS框架为基础

2.队列、集合数据结构的使用时机

3.单向bfs和双向bfs,达到目标的判断条件

4.何时扩展、如何一步步扩展=>的具体实现

//单向BFS
         Queue<string> q = new Queue<string>();//存放5个number,密码和1个状态位
         Queue<string> visited = new Queue<string>();//存放4个number,即密码
         while (q.Count > 0)
         {
             int sz = q.Count;
             for (int i = 0; i < sz; i++)
             {
                 string cur;//当前密码
                 //char[] list_temp = list.Clone() as char[];
                 cur = advance(q.Dequeue()).Remove(4, 1);
                 if (cur == "0000")
                 {
                     return step;
                 }
                 if (deadends.Contains(cur) || visited.Contains(cur))
                 {
                     continue;
                 }
                 visited.Enqueue(cur);
                 for (int j = 1; j < 9; j++)
                 {
                     q.Enqueue(cur+j.ToString());
                 }
             }
             step++;
         }
//双向BFS,此方法有待改进
         //头部bfs
         Queue<int> head_q = new Queue<int>();//存放当前的number
         Queue<int> head_visited = new Queue<int>();//存放访问过的number
         Queue<int> head_s = new Queue<int>();//存放待调整的状态参数
         //尾部bfs
         Queue<int> tail_q = new Queue<int>();//存放当前的number
         Queue<int> tail_visited = new Queue<int>();//存放访问过的number
         Queue<int> tail_s = new Queue<int>();//存放待调整的状态参数


         head_q.Enqueue(0);
         head_s.Enqueue(0);

         tail_q.Enqueue(m_target);
         tail_s.Enqueue(0);

         int h_step = -1;
         int t_step = -1;

         while (head_s.Count > 0&&tail_s.Count>0)
         {
             h_step++;
             int h_sz = head_s.Count;
             for (int j = 0; j < h_sz; j++)
             {

             
             int head = advance(head_q.Dequeue(), head_s.Dequeue());
             if (tail_visited.Contains(head))
             {
                 step = h_step + t_step;
                 return step;
             }
             if ((!locked.Contains(head))&&(!head_visited.Contains(head)))
             {
                 //将该节点的子节点放入队列
                 head_visited.Enqueue(head);
                 for (int i = 1; i < 5; i++)
                 {
                 head_q.Enqueue(head);
                 head_s.Enqueue(i);

                 head_q.Enqueue(head);
                 head_s.Enqueue(-i);
                 }
             }
             }

             t_step++;
             int t_sz = tail_s.Count;
             for (int j = 0; j < t_sz; j++)
             {

             
             int tail = advance(tail_q.Dequeue(), tail_s.Dequeue());
             if (head_visited.Contains(tail))
             {
                 step = h_step + t_step;
                 return step;
             }

             if ((!locked.Contains(tail)) && (!tail_visited.Contains(tail)))
             {
                 //将该节点的子节点放入队列
                 tail_visited.Enqueue(tail);
                 for (int i = 1; i < 5; i++)
                 {
                     tail_q.Enqueue(tail);
                     tail_s.Enqueue(i);

                     tail_q.Enqueue(tail);
                     tail_s.Enqueue(-i);
                 }
             }
             }
             
         }

需要改进的点:(2020.12.17)

  1. 不转数字,直接字符串与字符
  2. 用集合代替队列
  3. deadkey直接初始化到visited里
  4. 2个bfs使用轮换方法,轮流与对边比较、自我扩散(每次都只于最外侧比较)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值