个人学习笔记,记录以便后续复习
个人学习笔记,记录以便后续复习
个人学习笔记,记录以便后续复习
BFS核心思想就是把一些问题抽象成图,从一个点开始,向四周扩散。
算法框架
BFS问题的本质就是在一幅【图】中找到从起点start到终点target的最近距离。
框架如下:
//计算从起点start到终点target的最近距离
int BFS(Node start,Node target){
Queue<Node> q;//核心数据结构
Set<Node> visited;//避免回头路
q.offer(start);
visited.add(start);
int step=0;
while(q not empty){
int sz=q.size();
/*将当前队列中的所有节点向四周扩散*/
for(int i=0;i<sz;i++){
Node cur=q.poll();
/*重点:这里判断是否到达终点*/
if(cur is target) return step;
/*将cur的相邻节点加入队列*/
for(Node x:cur.adj())//cur.adj()泛指cur相邻的节点
if(x not in visited){
q.offer(x);
visited.add(x);
}
}
/*重点:在这里更新步数*/
step++;
}
}
二叉树的最小高度(111)
*怎么套用到框架里面?*首先,要明确起点start和目标target是什么,怎么判断达到了终点。
(root为start,终点为最靠近根结节点的那个叶节点。)
public class TreeNode{
int val;
TreeNode left;
TreeNode right;
TreeNode(int x){val=x;}
}
class Solution{
public int minDepth(TreeNode root){
Queue<TreeNode> q=new LinkedList<>();
q.offer(root);
int depth=1;
if(root==null) return 0;
while(!q.isEmpty()){
int sz=q.size();
for(int i=0;i<sz;i++){
TreeNode cur=q.poll();
if(cur.left==null && cur.right==null) return depth;
if(cur.left!=null) minDepth(cur.left);
if(cur.right!=null) minDepth(cur.right);
}
depth++;
}
return depth;
}
}
BFS的逻辑中,depth每增加一步,队列中所有节点都像前迈一步,齐头并进,可以在不遍历完整课树的条件下找到最短距离的。
解开密码锁密码的最小次数(752)
可以从“0000”开始,转一次,可以穷举出来8个基础密码,然后在这个基础密码上再开始转,直到穷举出所有可能的密码。
可以抽象成为一幅图,一个节点有8个相邻的节点。就是BFS问题。
每一位可以向上波动,也可以向下波动。
class Solution{
public String plusOne(String s,int j){
char[] ch=s.toCharArray();
if(ch[j]=='9') ch[j]='0';
else ch[j]+=1;
return new String(ch);
}
public String minusOne(Sting s,int j){
char[] ch=s.toCharArray();
if(ch[j]=='0') ch[j]='9];
else ch[j]-=1;
return new String(ch);
}
public int openLock(String[] deadends,String target){
Set<String> deads=new HashSet<>();
for(String s:deadends) deads.add(s);
Set<String> visited=new HashSet<>();
Queue<String> q=new LinkedList<>();
q.offer("0000");
visited.add("0000");
int step=0;
while(!q.isEmpy()){
String cur=q.poll();
if(deads.contains(cur)) continue;
if(cur.equals(target)) return step;
for(int j=0;j<4;j++){
String up=plusOne(cur,j);
if(!visited.contains(up)){
q.offer(up);
visited.add(up);
}
String down=minusOne(cur,j);
if(!visitd.contains(down)){
q.offer(down);
visited.add(down);
}
}
}
step++;
}
return -1;
}
}
双向BFS优化
传统BFS框架就是从起点开始向四周扩散,遇到终点时停止;而双向BFS则是从起点和终点同时开始扩散,当两边有交集的时候停止。但局限在于你要知道终点在哪里。与BFS框架相比,双向BFS不再使用队列,而是使用HashSet方便快速判断两个集合是否有交集。
public int openLock(String[] deadends,String target){
Set<String> deads=new HashSet<>();
for(String s:deadends) deads.add(s);
//用集合不用队列,可以快速判断元素是否存在
Set<String> q1=new HashSet<>();
Set<String> q2=new HashSet<>();
Set<String> visited=new HashSet<>();
int step=0;
q1.add("0000");
q2.add("0000");
//将q1中所有节点向周围扩散
while(!q1.isEmpy() && !q2.isEmpty()){
//哈希集合在遍历的过程中不能修改,用temp存储扩散结果
Set<String> temp=new HashSet<>();
for(String cur:q1){
if(deads.contains(cur)) continue;
if(q2.contains(cur)) return step;
visited(cur);
for(int j=0;j<4;j++){
String up=plusOne(cur,j);
if(!visited.contains(up)) temp.add(up);
String down=minusOne(cur,j);
if(!visitd.contains(down)) temp.add(down);
}
}
step++;
//temp相当于q1
//这里交换q1,q2,下一轮while就是扩散q2
q1=q2;
q2=temp;
}
return -1;
}