0
点赞
收藏
分享

微信扫一扫

2.21 BFS练习

律楷粑粑 2022-02-22 阅读 88

BFS

模板

// 计算从起点start到终点target 的最近距离
public int bfs(Node start,Node target){
	Queue<Node> q ;// 核心数据结构
    Set<Node> visited; // 避免走回头路
    
    q.offer(start) ; //将起点加入队列
    visited.add(start) ; 
    int step = 0 ;
    
    while(!q.isEmpty()) {
       int sz = q.size(); 
       // 将当前队列中的所有节点向四周扩散
        for(int i=0;i<sz;i++) {
       		Node cur = q.poll();
           //划重点:这里判断是否到达终点 
            if( cur == target) return step ;
            // 将cur的相邻节点加入队列
            for(Node x : cur.adj()) {
            	if(x not in visited) {
                	q.offer(x);
                    visited.add(x);
                }
            }
       }	
        // 划重点:更新步数在这里
        step++;
    }
}

397 整数替换

 public int integerReplacement(int n) {
 	if(n==1) return 0;
     Map<Long,Integer> map = new HashMap<>(); 
     Deque<Long> d = new ArrayDeque<>() ;
     d.addLast(n*1L); 
     map.put(n*1L,0);
     while(!d.isEmpty()) {
     	long t = d.pollFirst();  
        int step  = map.get(t); 
        long[] ns = t%2 == 0? new long[]{t/2} : new long[] {t+1,t-1} ; //每个节点可能的情况,都要加入队列
        for(long x : ns ){ 
        	if(x==1) return step +1; // 达到终点
            if(!map.containsKey(x)) { // 用map记录次数 如果已经有记录 就不用继续了。
            	map.put(x,step+1);
                d.addLast(x);
            }
        }
     }
     return -1;
 }

838 推多米诺

注意的是:需要有一个时间的判定。在相同的时间受到两个方向的力才保持不变。而time就是起时间记录的作用,比如在本位置,的下一步是向右倒下,那么对应的时间是time+1,只有当右边过来的向左倒下的时间也是time+1的时候,才保持中立。

public String pushDominoes(String dominoes) {
	char[] cs = dominoes.toCharArray(); 
    int n = cs.length ;
    int[] g= new int[n] ;
    Deque<int[]> d = new ArrayDeque<>();
    for(int i=0;i<n;i++) {
    	if(cs[i]=='.') continue ;
        int dire = cs[i] == 'L' ? -1 : 1;
        d.add(new int[]{i,1,dire});
        g[i] = 1; 
    }
    while(!d.isEmpty()) {
    	int[] info = d.pollFirst() ;
        int loc = info[0],time = info[1],dire = info[2];
        int ne = loc + dire; //下一个位置
        if(ne<0||ne>=n) continue ; // 越界
        if(g[ne]==0){ // 首次受力 
        	d.addLast(new int[]{ne,time+1,dire});
            g[ne] = time +1 ;
            cs[ne] = dire==-1?'L':'R'; 
        }else if(g[ne]==time+1) { // 多次受力
        	cs[ne] = '.';
        }
    	return String.valueOf(cs);
    }
}

752 打开转盘锁

public static int openLock(String[] deadends, String target) {
		 HashSet<String> set = new HashSet<>();
		 for(String str : deadends) set.add(str);  //将死锁的情况记录下来
		 Deque<String> deque = new ArrayDeque<>();
		 HashSet<String> set2 = new HashSet<>(); //用来记录已经遍历过的情况
		 deque.addLast("0000");
		 set2.add("0000");
		 int step = 0;
		 while(!deque.isEmpty()) {
			 int sz = deque.size();
			for(int n=0;n<sz;n++) { //不能少了双遍历的这一步
			 String poll = deque.poll(); //poll 或者是pollFirst 对应下面是 addLast
			 if(poll.equals(target)) return step;
			 if(set.contains(poll)) continue ; //不能在这里直接判定是否已经遍历过,因为前面先将“0000”加入了set2,此时如果直接判断就会跳出循环。
			 char[] cs1 = poll.toCharArray();
			 for(int i=0;i<4;i++) {
				 char[] cs2 = cs1.clone();
				 if(cs1[i]=='9') cs2[i] = '0';
				 else cs2[i] = (char) (cs1[i]+1);
				 String str = new String(cs2); //不能直接sc2.toString() 这样输出的是地址
				 if(!set2.contains(str)) {
					 deque.offer(str);
					 set2.add(str);
				 }
				 if(cs1[i]=='0') cs2[i] = '9';
				 else cs2[i] = (char) (cs1[i]-1);
				 String str2 = new String(cs2);
				 if(!set2.contains(str2)) {
					 deque.offer(str2);
					 set2.add(str2);
				 }
			 }
		}
			 step ++ ;
		 }
		 return -1;
	 }

}
举报

相关推荐

0 条评论