今日没有缺席。十一月的最后一天,收到了大物成绩。考场上的发挥决定了做题家的上限,对知识的温习程度兜底分数的下限。
二分法
有序数组 找中位数 时间复杂度O(log(m+n))
中位数的原理
两个序列合并的中位数,相当于在每个序列找到一个分割位置,这个位置符合:
即有两个分割条件:数量总和条件、数字大小条件
#include <limits.h>
#define MAX(a, b) (((a) >= (b)) ? (a) : (b))
#define MIN(a, b) (((a) <= (b)) ? (a) : (b))
double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size){
int halfSize;
int head1, tail1, half1, half2;
int nums1Left, nums1Right, nums2Left, nums2Right;
double ret;
//确保nums1Size比较小
if(nums1Size > nums2Size){
return findMedianSortedArrays(nums2, nums2Size, nums1, nums1Size);
}
//插空后,nums1和nums2的长度均为2numsSize+1,halfSize为两个合起来的长度的一半。
halfSize = nums1Size + nums2Size;
//开始对nums1进行二分
head1 = 0;
tail1 = 2 * nums1Size;
//小于等于可包含为空的情况
while (head1 <= tail1) {
half1 = head1 + (tail1 - head1) / 2;
//由于确保nums1Size比较小,half2肯定大于0
half2 = halfSize - half1;
//考虑边界情况
nums1Left = (half1 == 0) ? INT_MIN : nums1[(half1 - 1) / 2];
nums2Left = (half2 == 0) ? INT_MIN : nums2[(half2 - 1) / 2];
nums1Right = (half1 == 2 * nums1Size) ? INT_MAX : nums1[half1 / 2];
nums2Right = (half2 == 2 * nums2Size) ? INT_MAX : nums2[half2 / 2];
if (nums1Left > nums2Right) {
tail1 = half1 - 1;
} else if (nums2Left > nums1Right ) {
head1 = half1 + 1;
} else {
break;
}
}
ret = (MAX(nums1Left, nums2Left) + MIN(nums1Right, nums2Right)) / 2.0;
return ret;
}
limits.h 头文件决定了各种变量类型的各种属性。定义在该头文件中的宏限制了各种变量类型(比如 char、int 和 long)的值。
这些限制指定了变量不能存储任何超出这些限制的值,例如一个无符号可以存储的最大值是 255。
二分法查找,也称为折半法,是一种在有序数组中查找特定元素的搜索算法。
二分法查找的思路如下:
(1)首先,从数组的中间元素开始搜索,如果该元素正好是目标元素,则搜索过程结束,否则执行下一步。
(2)如果目标元素大于/小于中间元素,则在数组大于/小于中间元素的那一半区域查找,然后重复步骤(1)的操作。
(3)如果某一步数组为空,则表示找不到目标元素。
链接:https://blog.csdn.net/u012194956/article/details/79103843
***数量总和条件***满足:
使用符号填充方法,不管是奇偶的序列,填充后都会变成奇数序列。
在这里的必要性很重要,因为分割位置只需要选择序列1的任意一个数或字符上,均可在序列2找到某一个数或字符,符合分割后左边的数字总和等于右边的数字总和。
[1,2,3]
[1,1,3,3]
填充后
[#,1,#,2,#,3,#]
[#,1,#,1,#,3,#,3#]
填充后分割,只需要两个序列的位置index为:
half1 + half2 == halfSize == nums1Size + nums2Size
half1和half2表示扩充后的序列的分割位置,nums1Size和nums2Size表示原序列的总长度。
随后half1调整位置,half2只需要相应调整位置即可。
***数字大小条件***满足:
判断:1左<2右;2左<1右
- 若分割在数字上,则分割左右均取该数字;
- 若分割在字符上,则取分割左右的数字。
中位数的获取=分割点左边的最大值+分割点右边的最小值的平均数。
边界条件
- 序列为空
- 取到最左最右的情况
参照:https://leetcode-cn.com/problems/median-of-two-sorted-arrays/solution/cyu-yan-er-fen-fa-by-pang-san-jin-3/