[LeetCode]サマの個人記録_47

>>> 经典的图论问题
>>> 经典的三种解法———【DFS】【BFS】【并差集】
>>> 关键在于【visited/draw】数组的使用 >_<
class Solution {
    
    
	// DFS
    public int findCircleNum(int[][] isConnected) {
    
    
        int len = isConnected.length;
        boolean[] visited = new boolean[len];

        int cnt = 0;
        for(int i = 0; i < len; i++) {
    
    
            if(!visited[i]) {
    
    
                cnt++;
                DFS(isConnected, visited, i);
            }
        }
        return cnt;
    }

    private void DFS(int[][] isConnected, boolean[] visited, int node) {
    
    
        visited[node] = true;
        for(int i = 0; i < isConnected.length; i++) {
    
    
            if(isConnected[node][i] == 1 && !visited[i]) {
    
    
                DFS(isConnected, visited, i);
            }
        }
    }
}
class Solution {
    
    
    public int findCircleNum(int[][] isConnected) {
    
    
    	// BFS
        int len = isConnected.length;
        boolean[] visted = new boolean[len];

        int cnt = 0;
        Queue<Integer> queue = new LinkedList<>();
        for(int i = 0; i < len; i++) {
    
    
            if(!visted[i]) {
    
    
                cnt++;
                queue.offer(i);
                visted[i] = true;
                while (!queue.isEmpty()) {
    
    
                    int node = queue.poll();
                    for(int k = 0; k < len; k++) {
    
    
                        if(isConnected[node][k] == 1 && !visted[k]) {
    
    
                            queue.offer(k);
                            visted[k] = true;
                        }
                    }
                }
            }
        }
        return cnt;
    }
}
class Solution {
    
    
    public int findCircleNum(int[][] isConnected) {
    
    
    	// 并差集
        int len = isConnected.length;
        UnionSet unionSet = new UnionSet(len);
        for(int i = 0; i < len; i++) {
    
    
            for(int j = i + 1; j < len; j++) {
    
    
                if(isConnected[i][j] == 1) {
    
    
                    unionSet.union(i, j);
                }
            }
        }
        return unionSet.size;
    }
}


/*
 *【并差集模板(变式)】
 * 		1.使用了一个size变量,默认值为roots数组的长度
 * 		2.在合并(union)时,判断两个将要合并的节点是否已经一组,如果不是,则本次的合并导致size--
 */
class UnionSet {
    
    

    int size;
    int[] roots;

    public UnionSet(int len) {
    
    
        size = len;
        roots = new int[len];
        for(int i = 0; i < len; i++) {
    
    
            roots[i] = i;
        }
    }

    public int findRoot(int node) {
    
    
        if(node == roots[node]) {
    
    
            return node;
        }
        roots[node] = findRoot(roots[node]);
        return roots[node];
    }

    public void union(int node1, int node2) {
    
    
        if(!isUnion(node1, node2)) {
    
    
            roots[findRoot(node1)] = findRoot(node2);
            size--;
        }
    }

    public boolean isUnion(int node1, int node2) {
    
    
        return findRoot(node1) == findRoot(node2);
    }

}

 
 
 

ここに画像の説明を挿入

>>> 一个重要的优化操作是:每次n都模5,将n限制在01234,这样既能判断是否能被5整除又避免了n过大
>>> 两个小细节是:乘2的操作使用位运算;"<<"的优先级很低,甚至低于"+""n << 1 + A[i]"应该写成"(n << 1) + A[i]"
class Solution {
    
    
    public List<Boolean> prefixesDivBy5(int[] A) {
    
    
        int len = A.length;
        List<Boolean> res = new ArrayList<>();

        int n = 0;
        for(int i = 0; i < len; i++) {
    
    
            n = ((n << 1) + A[i]) % 5;
           res.add(n == 0);
        }
        return res;
    }
}

 
 
 

ここに画像の説明を挿入

>>> 本质还是数组按位相加———这类题使用三元表达式极其优雅
class Solution_989 {
    
    
    public List<Integer> addToArrayForm(int[] A, int K) {
    
    
        List<Integer> res = new LinkedList<>();
        int len = A.length;
        int i = len - 1;    // 数组下标
        int carry = 0;      // 进位      
        
        while (i >= 0 || K > 0) {
    
    
            int num1 = (i >= 0 ? A[i] : 0);
            int num2 = (K > 0 ? K % 10 : 0);
            int num3 = num1 + num2 + carry;
            res.add(0, num3 % 10);
            carry = num3 / 10;
            i--;        // 数组移动下标
            K /= 10;    // 数字移动下标
        }
        if(carry > 0) {
    
    
            res.add(0, carry);  // 最后的一个进位不要忘记 >_<
        }
        return res;
    }
}

 
 
 
 

 
 
 
 

 
 
 
 

END END E N D

おすすめ

転載: blog.csdn.net/m0_46202073/article/details/112308771