算法描述:
求出两个有序数组的中位数。
public class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
if (nums1 == null || nums1 == null)
throw new NullPointerException();
int nums1L = nums1.length;
int nums2L = nums2.length;
int length = nums1L + nums2L;
//需要一个计数器来记录比较次数(需要比较length/2 )
int count = 0;
//指示两个数组的当前位置
int i = 0;
int j = 0;
//检查数组nums1和nums2为空的情况
if (nums1L < 1 && nums2L < 1)
return 0;
else if (nums1L < 1) {
//元素个数为奇数
if (length == 1) return nums2[j];
if (length % 2 != 0) {
//如果数组1元素个数为0,从当前位置遍历数组2
while (j < nums2L) {
count++;
j++;
if (count == (length / 2)) return nums2[j];
}
} else {
//如果数组1元素个数为0,从当前位置遍历数组2
while (j < nums2L) {
count++;
j++;
if (count == (length / 2)) return ((double)nums2[j - 1] +nums2[j]) / 2;
}
}
} else if (nums2L < 1) {
if (length == 1) return nums1[i];
if (length % 2 != 0) {
//如果数组2元素个数为0,从当前位置遍历数组2
while (i < nums1L) {
count++;
i++;
if (count == (length / 2)) return nums1[i];
}
} else {
//如果数组2元素个数为0,从当前位置遍历数组1
while (i < nums1L) {
count++;
i++;
if (count == (length / 2)) return ((double)nums1[i - 1] +nums1[i]) / 2;
}
}
}
// 判断length是奇数还是偶数
//如果是奇数,则取中间的那一位
if (length % 2 != 0) {
//遍历这两个数组,有两种情况发生:1.在没到达边界前计算出中间位置2.到达边界以后算出中间位置
while (i < nums1L && j < nums2L) {
//当count = length / 2时,到了中间的位置,获取它的值
count++;
if (nums1[i] < nums2[j]) {
i++;
if (count == (length / 2) && i < nums1L) {
if (nums1[i] < nums2[j]) return nums1[i];
else return nums2[j];
} else if (count == (length / 2) && i == nums1L) {
if (nums1[ i- 1] < nums2[j]) return nums2[j];
else return nums1[ i - 1];
} else if (i == nums1L) break;
} else {
j++;
if (count == (length / 2) && j < nums2L) {
if (nums2[j] < nums1[i]) return nums2[j];
else return nums1[i];
} else if (count == (length / 2) && j == nums2L) {
if (nums2[ j - 1] < nums1[i]) return nums1[i];
else return nums2[ j - 1];
} else if (j == nums2L) break;
}
}
//数组到达边界,分析是哪种情况:1.数组1到达边界;2.数组2到达边界
if (i == nums1L) {
//如果数组1越界,从当前位置遍历数组2
while (j < nums2L) {
count++;
j++;
if (count == (length / 2)) return nums2[j];
}
} else if (j == nums2L) {
//如果数组2越界,从当前位置遍历数组1
while (i < nums1L) {
count++;
i++;
if (count == (length / 2)) return nums1[i];
}
}
} else {
//否则取中间两位的平均
//遍历这两个数组,有两种情况发生:1.在没到达边界前计算出中间位置2.到达边界以后算出中间位置
while (i < nums1L && j < nums2L) {
//当count = length / 2时,到了中间的位置,获取它的值
count++;
if (nums1[i] < nums2[j]) {
i++;
if (count == (length / 2) && i < nums1L) {
if (nums1[i] < nums2[j]) {
return ((double)nums1[i - 1] +nums1[i]) / 2;
}
else {
return ((double)nums2[j] + nums1[i - 1]) / 2;
}
} else if (count == (length / 2) && i == nums1L) {
return ((double)nums1[i - 1] +nums2[j]) / 2;
} else if (i == nums1L) break;
} else {
j++;
if (count == (length / 2) && j < nums2L) {
if (nums2[j] < nums1[i]) {
return ((double)nums2[j - 1] +nums2[j]) / 2;
}
else {
return ((double)nums1[i] + nums2[j - 1]) / 2;
}
} else if (count == (length / 2) && j == nums2L) {
return ((double)nums2[j - 1] +nums1[i]) / 2;
} else if (j == nums2L) break;
}
}
//数组到达边界,分析是哪种情况:1.数组1到达边界;2.数组2到达边界
if (i == nums1L) {
//如果数组1越界,从当前位置遍历数组2
while (j < nums2L) {
count++;
j++;
if (count == (length / 2)) return ((double)nums2[j] + nums2[j - 1]) / 2;
}
} else if (j == nums2L) {
//如果数组2越界,从当前位置遍历数组1
while (i < nums1L) {
count++;
i++;
if (count == (length / 2)) return ((double)nums1[i] + nums1[i - 1]) / 2;
}
}
}
return 0;
}
}
笔记:
- 变量定义在最前面,这样代码读起来更好;
- 方法要先进行传入参数的检查,确保传入参数正确;
- 对特殊情况要先考虑清楚,在这个题中,要考虑其中一个或两个元素个数都为的情况;
- 算法在考虑效率时,并列条件只考虑最复杂的一个条件。循环是主要的效率考虑。