zoukankan      html  css  js  c++  java
  • LeetCode解题报告—— Number of Islands & Bitwise AND of Numbers Range

    1. Number of Islands

    Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.

    Example 1:

    Input:
    11110
    11010
    11000
    00000
    
    Output: 1
    

    Example 2:

    Input:
    11000
    11000
    00100
    00011
    
    Output: 3

    思路:基本思路是利用DFS,遍历矩阵,遇到1的话就利用DFS将所有与其邻接的1全置为0,将计数器加1即可。

    public class Solution {
    
    private int n;
    private int m;
    
    public int numIslands(char[][] grid) {
        int count = 0;
        n = grid.length;
        if (n == 0) return 0;
        m = grid[0].length;
        for (int i = 0; i < n; i++){
            for (int j = 0; j < m; j++)
                if (grid[i][j] == '1') {
                    DFSMarking(grid, i, j);
                    ++count;
                }
        }    
        return count;
    }
    
    private void DFSMarking(char[][] grid, int i, int j) {
        if (i < 0 || j < 0 || i >= n || j >= m || grid[i][j] != '1') return;
        grid[i][j] = '0';
        DFSMarking(grid, i + 1, j);
        DFSMarking(grid, i - 1, j);
        DFSMarking(grid, i, j + 1);
        DFSMarking(grid, i, j - 1);
    }
    }

    2. Bitwise AND of Numbers Range

    Given a range [m, n] where 0 <= m <= n <= 2147483647, return the bitwise AND of all numbers in this range, inclusive.

    Example 1:

    Input: [5,7]
    Output: 4
    

    Example 2:

    Input: [0,1]
    Output: 0

    思路:奇数与偶数And,最后一位结果肯定是0。如果m和n不想等,那么这个range之间一定有奇数和偶数,它们and之后最后一位肯定是0,再和其它数字and最后一位还是0。这样确定了最后一位数字是0还是1之后将m和n右移一位再执行相同步骤,直到m和n相等为止,这个相等的部分and之后是保持原值的。

    public class Solution {
        public int rangeBitwiseAnd(int m, int n) {
            if(m == 0){
                return 0;
            }
            int moveFactor = 1;
            while(m != n){  // 这个循环能确定最后1位,2位...是0(只要此时的m和n不想等,这时的最后位结果一定是0),直至到二进制高位相同的部分
                m >>= 1;
                n >>= 1;
                moveFactor <<= 1;  // 记录往右移了多少次,即确定了末尾处的几个0,moveFactor应该是10....(1后面跟多个0) 这样的形式
            }
            return m * moveFactor;  // 此时的m剩下的是高位相同(不变的)部分,后面应该都是0,所以要乘以moveFactor来还原结果
        }
    }

    3. Course Schedule

    There are a total of n courses you have to take, labeled from 0 to n-1.

    Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]

    Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses?

    Example 1:

    Input: 2, [[1,0]] 
    Output: true
    Explanation: There are a total of 2 courses to take. 
                 To take course 1 you should have finished course 0. So it is possible.

    Example 2:

    Input: 2, [[1,0],[0,1]]
    Output: false
    Explanation: There are a total of 2 courses to take. 
                 To take course 1 you should have finished course 0, and to take course 0 you should
                 also have finished course 1. So it is impossible.
    

    Note:

    1. The input prerequisites is a graph represented by a list of edges, not adjacency matrices. Read more about how a graph is represented.
    2. You may assume that there are no duplicate edges in the input prerequisites.

    思路:和第一题一样,都是属于和图相关的题目,说到图的话,首先想到的是DFS和BFS。对于这题来说,如何把它建模成是一个图问题是个比较难的地方,根据输入得到的是一系列的边,现在一个想法是将输入转化成一个二维矩阵来考虑。也就是说现在一个对于图相关问题的通用思路是能不能将输入变成二维矩阵的形式。对于此题,可将每节课看成是矩阵的行索引和列索引,即行从0到n,列也从0到n,matrix[i][j] 值如果是1的话则表示从 i 到 j 是有边的,放在这题中就是说课程i 是课程j 的先决条件。这样的一个二维矩阵便可以用来表示一个有向图(这里让我想起了数据结构的那个弗洛伊德算法)。

    第一个的图转化为矩阵完成了,对于此题还不够,因为一个课程可能有多个先决课程,对应到图中来说就是一个节点的入度会大于1,只有当先决课程都满足的情况下才能take这个课程。那么还要记录每个节点的入度数目,如果某个节点的入度数是0则表示这是个开始节点,也就是说如果我们需要遍历整个图的话,是从这些节点开始的。那么现在思路很明显了,从这些开始节点开始遍历整个图,如果所有节点都能遍历得到那么则说明全部课程是可以完成的,这个过程中只有一点要注意的是对于入度数大于等于1的节点的处理情况。简而言之在BFS或DFS遍历图的节点时,要加一个判断条件看看这个节点是否符合不同题目所给出的实际要求。

    public boolean canFinish(int numCourses, int[][] prerequisites) {
        int[][] matrix = new int[numCourses][numCourses]; // 矩阵来表示整个有向图
        int[] indegree = new int[numCourses];  // 记录每个图节点的入度数,放在这里就是每个课程需要的前提课程是多少个
        
        for (int i=0; i<prerequisites.length; i++) {  // 将从i到j的有向边转化为矩阵形式
            int ready = prerequisites[i][0];
            int pre = prerequisites[i][1];
            if (matrix[pre][ready] == 0)  // avoid duplicate case
                indegree[ready]++; 
            matrix[pre][ready] = 1;
        }
        
        int count = 0;
        Queue<Integer> queue = new LinkedList();
        for (int i=0; i<indegree.length; i++) {
            if (indegree[i] == 0) queue.offer(i);  // 将入度为0的节点作为遍历的开始节点推入队列中
        }
        while (!queue.isEmpty()) {  // BFS,直到队列全部出完为止
            int course = queue.poll();
            count++;  // 记录总共遍历了多少course
            for (int i=0; i<numCourses; i++) {
                if (matrix[course][i] != 0) {  // 如果目前出队列的course是课程i的前提课程,那么课程i的入度数减1
                    if (--indegree[i] == 0)  // 如果课程i的前提课程都满足了,那么可以take这个课程,将其推入队列中
                        queue.offer(i);
                }
            }
        }
        return count == numCourses;  // 如果都遍历到了则表示可以完成所有cousre
    }
  • 相关阅读:
    vijos 1426
    2455 繁忙的都市
    2104 删除物品
    3235 战争
    BZOJ 2962
    COGS 265 线段覆盖
    P2184 贪婪大陆
    0729模拟赛解题报告
    BZOJ 1012
    BZOJ 2763
  • 原文地址:https://www.cnblogs.com/f91og/p/9121592.html
Copyright © 2011-2022 走看看