算法day28

第一题

295. 数据流的中位数

        本题我们是求解给定数组的中位数。且由于需要随时给数组添加元素,所以我们要求解该动态数组的中位数,所以本题最关键的就是维护数组在添加元素之后保持有序的排序,这样就能很快的求解中位数;

        解法:我们使用大小堆来维护数据流的中位数

        如上图所示,我们将当前数组从中间分为两部分,左边部分的数据放入到大根堆,右边数据放入到小根堆,且两个堆的数据长度只有两种情况,要么两的个堆里面数据相同,要么左堆的长度比右堆的长度多一;

        接下来就是分类讨论添加数据的详细情况:

步骤一:

        定义大根堆的堆顶元素为x,里面元素的个数为m;小根堆堆顶的元素为y,里面元素的个数为n;

步骤二:

        当m等于n时:
        添加元素nums小于等于x或者当前两个堆都为空时,nums元素直接进入到左边大根堆;

        添加元素nums大于x时,nums元素首先进入到右边小根堆,然后将右边小根堆的堆顶元素放入到左边大根堆中;

步骤三:

        当m等于n+1时:

        添加元素nums大于x时,nums元素直接进入到右边小根堆;

        添加元素nums小于等于x时,nums元素首先进入到左边大根堆,然后将左边大根堆的堆顶元素放入到右边小根堆中;   

步骤四:

        根据情况求取该数组的中位数;

综上所述,代码如下:

class MedianFinder {
    PriorityQueue<Integer> left;
    PriorityQueue<Integer> right;

    public MedianFinder() {
        left = new PriorityQueue<Integer>((a,b) -> b - a);
        right = new PriorityQueue<Integer>((a,b) -> a - b);
    }
    
    public void addNum(int num) {
        if(left.size() == right.size()){
            if(left.isEmpty() || num <= left.peek()){
                left.offer(num);
            }else{
                right.offer(num);
                left.offer(right.poll());
            }
        }else{
            if(num <= left.peek()){
                left.offer(num);
                right.offer(left.poll());
            }else{
                right.offer(num);
            }
        }
    }
    
    public double findMedian() {
        if(left.size() == right.size()) return (left.peek() +right.peek())/2.0;
        else return left.peek();
    }
}

/**
 * Your MedianFinder object will be instantiated and called as such:
 * MedianFinder obj = new MedianFinder();
 * obj.addNum(num);
 * double param_2 = obj.findMedian();
 */

  

第二题

733. 图像渲染

解法:bfs层序遍历

层序遍历如下所示:

假设当前的当前位置如下所示:

第二部就是找到其相邻的:

第三部就是找到第二部中相邻的:

依次类推;

本题的解题步骤如下:

综上所述,代码如下:

步骤一:

        创建一个队列,将当前的元素放入到队列里面,并将元素改变颜色;

步骤二:

        将队列中的元素先拿出来一个,分析出该元素的坐标,采用象限数组的方式来遍历该元素的上下左右四个位置的元素;

        即如下所示:

        如果该被遍历到的元素满足条件就将该元素放入到队列中,并将该元素按要求变色;

步骤三:就这样一一拿出队列中的元素,一直重复,直到队列为空为止;

class Solution {
    //象限坐标数组
     int[] dx = {0,0,1,-1};
     int[] dy = {1,-1,0,0};
    public int[][] floodFill(int[][] image, int sr, int sc, int color) {
        int prev = image[sr][sc];//统计刚开始的颜色
        if(prev == color) return image;//处理边界情况
            Queue<int[]> q = new LinkedList<>();
            q.add(new int[]{sr,sc});
            int m = image.length,n = image[0].length;
           
            while(!q.isEmpty()){
                int[] t = q.poll();
                int a = t[0],b=t[1];//取出收个点的x,y周坐标
                //该坐标的上下左右四个点,用向量数组坐标的方法来展示
                 image[a][b] = color;
                for(int i = 0;i<4;i++){
                    int x = a + dx[i],y = b + dy[i];
                    if(x >= 0 && x <m && y >= 0 && y < n && image[x][y] == prev){
                        q.add(new int[]{x,y});
                    }
                }

            }
            return image;
    }
}

第三题

200. 岛屿数量

示例一:

示例二:

解法:本题采用bfs层序遍历的方法,同时采用象限数组小技巧;

本题重新定义一个长度宽度与原题相似的布尔数组vis,每当遍历到一个元素且满足该题意要求是,将vis数组里面相对应位置的元素定义为true,这样在遍历的时候防治该元素被二次遍历;

        总体的解题思路如上题故事,代码如下所示:

class Solution {
    //象限坐标数组
     int[] dx = {0,0,1,-1};
     int[] dy = {1,-1,0,0};
     boolean[][] vis = new boolean[301][301];
     int m,n;
    public int numIslands(char[][] grid) {
        m = grid.length;
        n = grid[0].length;
        int ret = 0;
        for(int i = 0;i < m ;i++){
            for(int j = 0;j < n ;j++){
                if(grid[i][j] == '1' && !vis[i][j]){
                    ret++;
                    bfs(grid,i,j);
                }
            }
        }
        return ret;
    }

    public void bfs(char[][] grid,int i,int j){
        Queue<int[]> q = new LinkedList<>();
        q.add(new int[]{i,j});
        vis[i][j] = true;
        while(!q.isEmpty()){
            int[] t = q.poll();
            int a = t[0],b = t[1];
            for(int s = 0;s < 4;s++){
                int x = a +dx[s],y = b + dy[s];
                if(x >= 0 && x <m && y >= 0 && y < n && grid[x][y] == '1' && !vis[x][y]){
                    q.add(new int[]{x,y});
                    vis[x][y] = true;
                }
            }
        }
    }
}

ps:本次的内容就到这里了,如果对你有所帮助的话就请一一键三连哦!!! 

  • 39
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值