【算法】解题总结:剑指Offer 63 数据流中的中位数、剑指Offer 65 矩阵中的路径

JZ63 数据流中的中位数

(中等)

题目

描述
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。

示例
输入:
[5,2,3,4,1,6,7,0,8]
返回值:
"5.00 3.50 3.00 3.50 3.00 3.50 4.00 3.50 4.00 "
说明:
数据流里面不断吐出的是5,2,3…,则得到的平均数分别为5,(5+2)/2,3…

思路

(我对题意建议:这道题,上来看到了“数据流”这个词,我的直接反应就是怎么遇到了一个用I/O流的题,太少见了,是用数据流在后台算法中读数据吗?但之后才发现我I/O数据流没关系,我认为出题人很不注重措辞的严谨性,用“数组”,或者“序列”多好呢)

这道题我想到的第一种算法就是用直接插入排序来解决,因为求序列的中位数的前提是要求序列有序,而使得序列有序的操作对于此题来说,可以放在Insert()方法中实现——即在插入时就按有序比较来插入,也可以放在GetMedian()方法中——即仅每次求中位数时,才对序列进行排序,之后求中位数,所有由于我想到的是直接插入排序,因此自然就将排序的工作和插入的工作放在一起来做了,也就是前一种方法,在Insert()方法中实现,其他内容也没必要阐述了,直接插入排序无非就是将待插入值先与序列中各值进行比较,找到插入点,后移插入点及其之后元素,将待插入值插入插入点即可(详细解析请看之前文章:Java实现七种【排序算法】+图解+完整代码+分析

在做完后,发现此题还有一种解法,用堆排序去实现,用一个小根堆维护中位数及其左边的元素,用一个大根堆维护中位数及其右边的元素,最后的中位数,则为这两个大小根堆的根结点的值其中的一个或是两个的平均值(奇偶个数不确定)。

实现

public class Solution {
    double[] nums = new double[101];
    int len = 0;

    public void Insert(Integer num) {
        boolean flag = false;
        for (int i = 0; i < len; i++) {
            if (num <= nums[i]) {
                for (int j = len; j >= i; j--) {
                    nums[j + 1] = nums[j];
                }
                nums[i] = num;
                flag = true;
                len++;
                break;
            }
        }
        if (!flag) {
            nums[len++] = num;
        }
    }

    public Double GetMedian() {
        if (len % 2 == 0) {
            return (nums[len / 2 - 1] + nums[len / 2]) / 2;
        } else {
            return nums[len / 2];
        }
    }
}

在这里插入图片描述

JZ65 矩阵中的路径

(中等)

题目

描述
在这里插入图片描述

示例
在这里插入图片描述

我的解法——思路正确,代码报错

这是一道迷宫问题首先判断传入的数组是否为空值,增加容错性,在两次 for 循环中,将每个点都尝试作为起点,直到成功,同时本着不破坏原数组的前提下,每次创建一个复制数组,来进行接下来需要改变数组中值的操作(如走过,就标记 ‘#’),递归操作每个起点开始的迷宫数组,若碰到边界,或是走过,就返回 false,如果当前值与待配对值不相等,也返回 false,如果相等,同时又匹配了最后一个字符,那么返回 true,如果仍需匹配,那么再从此点进行上下左右的递归匹配,同时因本次的成功匹配,用于记录当前匹配位置的下标也应右移。

public class Solution {
    char[] wordArray = null; //存储字符串word
    int rowNum = 0;
    int colNum = 0;

    public char[][] copyDeepChar(char[][] matrix) {

		if (matrix == null || matrix.length == 0
                || word == null || word.length() == 0) {
            return false;
        }
        
        char[][] copy = new char[rowNum][colNum];
        for (int i = 0; i < rowNum; i++) {
            for (int j = 0; j < colNum; j++) {
                copy[i][j] = matrix[i][j];
            }
        }
        return copy;
    }

    public boolean hasPath (char[][] matrix, String word) {
        this.wordArray = word.toCharArray();
        this.rowNum = matrix.length;
        this.colNum = matrix[0].length;

        for (int i = 0; i < rowNum; i++) {
            for (int j = 0; j < colNum; j++) {
                //每次都要复制一次,因为每次都会因走过为标记 '#'
                char[][] myMatrix = copyDeepChar(matrix);

                if (dfs(myMatrix, i, j, 0)) {
                    return true;
                }
            }
        }

        return false;
    }

    public boolean dfs(char[][] myMatrix, int i, int j, int index) {
        //出界,或走过
        if (i < 0 || i >= rowNum || j < 0 || j >= colNum || myMatrix[i][j] == '#') {
            return false;
        }

        

        //不相等
        if (myMatrix[i][j] != wordArray[index]) {
            return false;
        }
        
        //匹配成功
        if (index == wordArray.length - 1) {
            return true;
        }

        //相等,移动下标
        index++;
        myMatrix[i][j] = '#'; //表示已经走过
        return dfs(myMatrix, i + 1, j, index + 1) || dfs(myMatrix, i - 1, j, index + 1)
                || dfs(myMatrix, i, j - 1, index + 1) || dfs(myMatrix, i, j + 1, index + 1);
    }
}

之后学习了别人的实现

学习自:https://blog.nowcoder.net/n/3ef094bfeb0244e59a40340963fc1eab?f=comment

这段正确的代码,和我想的思路是大体相同的,但是我的提交报错,我并没有找到问题在哪
在这里插入图片描述

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

超周到的程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值