leetcode-探索队列

1.构建自己的循环队列
/*
课本原题
*/
public class MyCircularQueue {
    
    
    private int[] data;
    private int head;
    private int tail;
    private int size;
    
    public MyCircularQueue(int k) {
    
    
        data = new int[k];
        head = -1;
        tail = -1;
        size = k;
    }
    
    public boolean enQueue(int value) {
    
    
        if (isFull() == true) {
    
    
            return false;
        }
        if (isEmpty() == true) {
    
    
            head = 0;
        }
        tail = (tail + 1) % size;
        data[tail] = value;
        return true;
    }
    
    public boolean deQueue() {
    
    
        if (head==tail&&head==-1){
    
    
            return false;
        }
        //当只剩下一个元素时
        else if (head==tail){
    
    
            head = -1;
            tail = -1;
            return true;
        }else {
    
    
            head = (head+1)%size;
            return true;
        }
    }
  
    public int Front() {
    
    
        if (isEmpty()==true){
    
    
            return -1;
        }
        return data[head];
    }
   
    public int Rear() {
    
    
        if (isEmpty()==true){
    
    
            return -1;
        }
        return data[tail];
    }

    public boolean isEmpty() {
    
    
        return head==-1;
    }
    
    public boolean isFull() {
    
    
        return ((tail + 1) % size) == head;
    }

}
2.利用定义好的库中的队列
public class Que {
    
    
    public static void main(String[] args) {
    
    
        Queue<Integer> queue = new LinkedList<Integer>();
        System.out.println(queue.peek());
        queue.add(1);
        System.out.println(queue.peek());
    }

}
3.岛屿数量:看着题目挺难懂,但是看一下测试用例就明白了,岛屿即连在一起的1,岛屿的数量就是有多少个连在一起的集合1/*
执行用时:3 ms, 在所有 Java 提交中击败了47.42%的用户
内存消耗:41.8 MB, 在所有 Java 提交中击败了6.25%的用户
*/
public class Solution {
    
    
    public int numIslands(char[][] grid) {
    
    
        if (grid == null || grid.length == 0) return 0;
        int count = 0;//记录岛屿的数量
        int row = grid.length, colums = grid[0].length;
        int i, j;
        for (i = 0; i < row; i++) {
    
    
            for (j = 0; j < colums; j++) {
    
    
                if (grid[i][j] == '1') {
    
    
                    bfs(row, colums, i, j, grid);
                    count++;
                }
            }
        }
        return count;
    }
	//利用队列,进行广度优先遍历,将连在一起的1变成0.
    private void bfs(int row, int colums, int i, int j, char[][] grid) {
    
    
        //利用队列存储位置
        Queue<Integer>  queue= new LinkedList<Integer>();
        queue.add(i*colums+j);
        //分析上下左右是否为1
        while (!queue.isEmpty()){
    
    
            int temp = queue.remove();
            int a = temp/colums, b = temp%colums;
            grid[a][b]=0;
            if (a-1>=0&&grid[a-1][b]=='1'){
    
    
                queue.add((a-1)*colums+b);
                grid[a-1][b]='0';
            }
            if (a+1<row&&grid[a+1][b]=='1'){
    
    
                queue.add((a+1)*colums+b);
                grid[a+1][b]='0';
            }
            if (b-1>=0&&grid[a][b-1]=='1'){
    
    
                queue.add(a*colums+b-1);
                grid[a][b-1]='0';
            }
            if (b+1<colums&&grid[a][b+1]=='1'){
    
    
                queue.add(a*colums+b+1);
                grid[a][b+1]='0';
            }
        }
    }
}
4.二叉树的最小高度:利用labuladong大佬的框架
/*
执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:39.8 MB, 在所有 Java 提交中击败了5.13%的用户
*/
public class Solution {
    
    
    
    public class TreeNode {
    
    
        int val;
        TreeNode left;
        TreeNode right;
        TreeNode(int x) {
    
    
            val = x;
        }
    }

    //offer、poll当出现异常时会返回false,而add,remove会抛出异常
    public int minDepth(TreeNode root) {
    
    
        if (root==null)  return 0;
        Queue<TreeNode> treeNodes = new LinkedList<TreeNode>();
        treeNodes.offer(root);
        int count = 1;
        while(!treeNodes.isEmpty()){
    
    
            int len = treeNodes.size();
            int i ;
            for(i=0;i<len;i++){
    
    
                TreeNode node = treeNodes.poll();
                if (node.left==null&&node.right==null){
    
    
                    return count;
                }
                if (node.left!=null){
    
    
                    treeNodes.offer(node.left);
                }
                if (node.right!=null){
    
    
                    treeNodes.offer(node.right);
                }

            }
            //当循环完树的一层时,层数加一
            count++;
        }
        return count;
    }
}
5.打开转盘锁(单向BFS:利用labuladong大佬的框架)
/*
执行用时:90 ms, 在所有 Java 提交中击败了77.25%的用户
内存消耗:45.6 MB, 在所有 Java 提交中击败了16.67%的用户
*/
class Solution {
    
    

    //进行转盘锁状态转移,每位数字进行加1或减1操作
    String up(int i, String s) {
    
    
        char[] ss = s.toCharArray();
        if (ss[i] == '9') {
    
    
            ss[i] = '0';
        } else {
    
    
            ss[i] += 1;
        }
        return new String(ss);
    }

    String down(int i, String s) {
    
    
        char[] ss = s.toCharArray();
        if (ss[i] == '0') {
    
    
            ss[i] = '9';
        } else {
    
    
            ss[i] -= 1;
        }
        return new String(ss);
    }

    
    int openLock(String[] deadends, String target) {
    
    
        //记录死亡数字
        Set<String> deads = new HashSet<String>();
        for (String s : deadends) deads.add(s);
        //记录浏览过的数字,减少循环
        Set<String> visited = new HashSet<>();
        Queue<String> queue = new LinkedList<String>();
        queue.offer("0000");
        visited.add("0000");
        int count = 0;
        while (!queue.isEmpty()) {
    
    
            int size = queue.size();
            for (int i = 0; i < size; i++) {
    
    
                String s = queue.poll();
                //当死亡数字包含S时,跳过该数字以及该数字每位加1或减1的数字,进行下一位数字判断。
                if (deads.contains(s)) {
    
    
                    continue;
                }
                if (s.equals(target)) {
    
    
                    return count;
                }
                //对每位数字上的4位进行加1或减1操作
                for (int j = 0; j < 4; j++) {
    
    
                    String data = up(j, s);
                    if (!visited.contains(data)) {
    
    
                        queue.offer(data);
                        visited.add(data);
                    }
                    data = down(j, s);
                    if (!visited.contains(data)) {
    
    
                        queue.offer(data);
                        visited.add(data);
                    }
                }
            }
            count++;
        }
        //当循环完成都没找到的话,就说明没有方法能转到该数字
        return -1;
    }
}
6.打开转盘锁(双向BFS:利用labuladong大佬的框架)
传统的 BFS 框架就是从起点开始向四周扩散,遇到终点时停止;而双向 BFS 则是从起点和终点同时开始扩散,当两边有交集的时候停止,但是双向BFS必须知道重点在哪,例如求二叉树的最小高度就不能用双向BFS.
/*
执行用时:31 ms, 在所有 Java 提交中击败了92.17%的用户
内存消耗:40.4 MB, 在所有 Java 提交中击败了33.33%的用户
*/
class Solution {
    
    
    String up(int i, String s) {
    
    
        char[] ss = s.toCharArray();
        if (ss[i] == '9') {
    
    
            ss[i] = '0';
        } else {
    
    
            ss[i] += 1;
        }
        return new String(ss);
    }

    String down(int i, String s) {
    
    
        char[] ss = s.toCharArray();
        if (ss[i] == '0') {
    
    
            ss[i] = '9';
        } else {
    
    
            ss[i] -= 1;
        }
        return new String(ss);
    }

   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(target);
    
    while (!q1.isEmpty() && !q2.isEmpty()) {
    
    
        // 哈希集合在遍历的过程中不能修改,用 temp 存储扩散结果
        Set<String> temp = new HashSet<>();

        /* 将 q1 中的所有节点向周围扩散 */
        for (String cur : q1) {
    
    
            /* 判断是否到达终点 */
            if (deads.contains(cur))
                continue;
            if (q2.contains(cur))
                return step;
            visited.add(cur);

            /* 将一个节点的未遍历相邻节点加入集合 */
             for (int j = 0; j < 4; j++) {
    
    
                    String data = up(j, cur);
                    if (!visited.contains(data)) {
    
    
                        temp.add(data);

                    }
                    data = down(j, cur);
                    if (!visited.contains(data)) {
    
    
                        temp.add(data);

                    }
                }
      
    }
     /* 在这里增加步数 */
        step++;
        // temp 相当于 q1
        // 这里交换 q1 q2,下一轮 while 就是扩散 q2
        q1 = q2;
        q2 = temp;
}
return-1;

}
}
    

7.完全平方数(如下面图片你所示)

在这里插入图片描述


/*
执行用时:336 ms, 在所有 Java 提交中击败了9.59%的用户
内存消耗:262.4 MB, 在所有 Java 提交中击败了5.26%的用户
*/
class Solution {
    
    
    public int numSquares(int n) {
    
    
        if (n==0) return 0;
        //利用nums存储值小于等于n完全平方数
        ArrayList<Integer> nums = new ArrayList<Integer>();
        for (int i =1;i*i<=n;i++){
    
    
            nums.add(i*i);
        }
        Queue<Integer> queue = new LinkedList<Integer>();
        queue.add(n);
        
        int count = 1;
        while(!queue.isEmpty()){
    
    
            int size = queue.size();
            for (int i=0;i<size;i++){
    
    
                Integer temp = queue.remove();
                for (Integer integer:nums){
    
    
                    //当某一层的数等于完全平方数时,即找到了答案
                    if (temp.equals(integer)){
    
    
                        return count;
                    }else if (temp<integer){
    
    
                        continue;
                    }else {
    
    
                        queue.add(temp-integer);
                    }
                }
            }
            count++;
        }
        return count;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_41458842/article/details/106906141