LeetCode-搜索

DFS

1. 岛屿的最大面积

岛屿的最大面积

package dfs;

import java.util.Arrays;

public class Solution_island {
    public static int maxAreaOfIsland(int[][] grid) {
        if(null == grid || grid.length == 0 || (grid.length == 1 && grid[0].length == 0))
            return 0;
        int max = Integer.MIN_VALUE;
        int row = grid.length;
        int col = grid[0].length;
        for(int i = 0; i < row; i++){
            for(int j = 0; j < col; j++){
                if(grid[i][j] == 1){
                    max = Math.max(max, process(grid, i, j));
                }
            }
        }
        return max;
    }

    public static int process(int[][] grid, int a, int b){
        if(a < 0 || a >= grid.length || b < 0 || b >= grid[0].length || grid[a][b] == 0) return 0;
        int count = 1;
        grid[a][b] = 0;
        count += process(grid, a, b + 1) + process(grid, a + 1, b) + process(grid, a, b - 1) + process(grid, a - 1, b);
        return count;
    }

    public static void main(String[] args) {
        int[][] grid = {{1,0,1},{1,1,0},{0,0,1}};
        System.out.println(maxAreaOfIsland(grid));
    }
}

2. ***朋友圈

https://leetcode-cn.com/problems/friend-circles/

dfs

    public static int findCircleNum(int[][] M) {
        if(M == null || M.length == 0 || (M.length == 1 && M[0].length == 0)){
            return 0;
        }
        int row = M.length;
        int[] flag = new int[row];
        int count = 0;
        for(int i = 0; i < row; i++){
            if(flag[i] == 0){
                flag[i] = 1;
                dfs(M, flag, i);
                count++;
            }
        }
        return count;
    }

    public static void dfs(int[][] arr, int[] flag, int k){
        for(int i = 0; i < arr.length; i++){
            if(arr[k][i] == 1 && flag[i] == 0){
                flag[i] = 1;
                dfs(arr, flag, i);
            }
        }
    }

bfs

public static int findCircleNum(int[][] M) {
    if(M == null || M.length == 0 || (M.length == 1 && M[0].length == 0)){
        return 0;
    }
    int row = M.length;
    int[] flag = new int[row];
    int count = 0;
    Queue<Integer> queue = new LinkedList<>();
    for(int i = 0; i < row; i++){
        if(flag[i] == 0){
            count++;
            flag[i] = 1;
            queue.add(i);
            while(!queue.isEmpty()){
                int c = queue.poll();
                for(int j = 0; j < row; j++){
                    if(M[c][j] == 1 && flag[j] == 0){
                        flag[j] = 1;
                        queue.add(j);
                    }
                }
            }
        }
    }
    return count;
}

并查集

static int find(int parent[], int i) {
    if (parent[i] == -1)
        return i;
    return find(parent, parent[i]);
}

static void union(int parent[], int x, int y) {
    int xset = find(parent, x);
    int yset = find(parent, y);
    if (xset != yset)
        parent[xset] = yset;
}
public static int findCircleNum(int[][] M) {
    int[] parent = new int[M.length];
    Arrays.fill(parent, -1);
    for (int i = 0; i < M.length; i++) {
        for (int j = 0; j < M.length; j++) {
            if (M[i][j] == 1 && i != j) {
                union(parent, i, j);
            }
        }
    }
    int count = 0;
    for (int i = 0; i < parent.length; i++) {
        System.out.print(parent[i] + " ");
        if (parent[i] == -1)
            count++;
    }
    System.out.println(" ");
    return count;
}

BFS

1.腐烂的橘子

994. 腐烂的橘子

public class Solution_994 {
    public static int orangesRotting(int[][] grid) {
        if(grid == null || grid.length == 0 || (grid.length == 1 && grid[0].length == 0 )){
            return 0;
        }
        //上下左右
        int[] x = {-1, 1, 0, 0};
        int[] y = {0, 0,  -1, 1};
        int row = grid.length;
        int col = grid[0].length;
        //广度优先搜索,将感染的橘子加入对列
        Queue<Integer> queue = new LinkedList<>();
        //value值为每个橘子被感染时,所代表的时间
        HashMap<Integer, Integer> map = new HashMap<>();
        int ans = 0;
        for(int i = 0; i < row; i++){
            for(int j = 0; j < col; j++){
                if(grid[i][j] == 2){
                    //矩阵中的每个元素,可以根据坐标换算出唯一索引
                    int code = i * col + j;
                    queue.add(code);
                    //矩阵中原始腐坏的橘子,腐坏时间为0
                    map.put(code, 0);
                }
            }
        }
        while(!queue.isEmpty()){
            int code = queue.remove();
            int r = code / col;
            int c = code % col;
            for(int i = 0; i < 4; i++){
                int rr = r + x[i];
                int cc = c + y[i];
                if(rr >= 0 && rr < row && cc >= 0 && cc < col && grid[rr][cc] == 1){
                    grid[rr][cc] = 2;
                    int code_infect = rr * col + cc;
                    queue.add(code_infect);
                    map.put(code_infect, map.get(code) + 1);
                    ans = map.get(code) + 1;
                }
            }
        }
        for(int[] arr : grid){
            for(int v : arr){
                if(v == 1){
                    return -1;
                }
            }
        }
        return ans;
    }

    public static void main(String[] args) {
//        int[][] grid = {{2,1,1}, {1,1,0}, {0,1,1}};
        int[][] grid = {{1, 2}};
        System.out.println(orangesRotting(grid));
    }
}

二分搜索

1.搜索旋转排序数组

33. 搜索旋转排序数组

我的解题方法比较麻烦,创建了一个新的方法用于对下标的控制。实际上用两个变量l和r,然后用一个while循环就可以。

关键点:使用二分,将数组分成两部分。其中一部分有序,一部分无序。使用nums[0] < nums[mid]判断有序的部分,因为左半部分无序,右半部分肯定有序。

public static int search(int[] nums, int target) {
    if(nums == null || nums.length == 0){
        return -1;
    }
    int l = 0, r = nums.length - 1;
    int mid;
    while(l <= r){
        mid = (l + r) / 2;
        if(nums[mid] == target){
            return mid;
        }
        if(nums[0] < nums[mid]){//左半部分有序
            if(nums[0] <= target && target < nums[mid]){
                r = mid - 1;
            }else {
                l = mid + 1;
            }
        }else{//右半部分有序
            if(nums[mid] < target && target < nums[r]){
                l = mid + 1;
            }else{
                r = mid - 1;
            }
        }
    }
    return -1;
}

2. 在排序数组中查找元素的第一个和最后一个位置

34. 在排序数组中查找元素的第一个和最后一个位置

要求:时间复杂度为O(logN)

抠边界

    //返回数组中第一个大于等于target的值的下标
    private static int binarySearch(int[] nums, int target){
        int start = 0;
        int end = nums.length;
        while(start < end){
            int mid = (start + end) / 2;
            if(nums[mid] == target){
                end = mid;
            }else if(nums[mid] < target){
                start = mid + 1;
            }else{
                //本来我写的是end = mid - 1,但是不对呀
                //因为最后return start,所以尽量让start右移
                end = mid;
            }
        }
        return start;
    }

    public static int[] searchRange(int[] nums, int target){
        int[] defaultArr = {-1, -1};
        int left = binarySearch(nums, target);
        if(left == nums.length || nums[left] != target){
            return defaultArr;
        }
        defaultArr[0] = left;
        //注意这里
        defaultArr[1] = binarySearch(nums, target + 1) - 1;
        return defaultArr;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值