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
这段正确的代码,和我想的思路是大体相同的,但是我的提交报错,我并没有找到问题在哪