第四题:求两个有序数组的中位数(Median of Two Sorted Arrays)

2024-08-24 13:28

本文主要是介绍第四题:求两个有序数组的中位数(Median of Two Sorted Arrays),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目描述:

给定两个大小为 m 和 n 的有序数组 nums1 和 nums2,请你找出这两个有序数组的中位数。

示例:

  1. 输入:nums1 = [1, 3]nums2 = [2]
    输出:2.0

  2. 输入:nums1 = [1, 2]nums2 = [3, 4]
    输出:2.5

要求: 你必须在对数时间复杂度 O(log(min(m, n))) 内解决这个问题。

解题思路

  1. 二分查找方法(最优解法)

    这个问题的核心是利用二分查找算法在两个有序数组中找到中位数。我们可以将问题转化为在两个数组中寻找一个分割点,使得左侧的元素总是小于右侧的元素,并且左侧的元素数量与右侧的元素数量尽可能相等。

    具体步骤如下:

    1. 确保 nums1 的长度小于等于 nums2,如果不是,则交换它们。

    2. 对于较短的数组 nums1,使用二分查找来确定分割点。分割点将数组 nums1 划分为 left1 和 right1,同时在 nums2 中确定对应的分割点 left2 和 right2

    3. 根据当前的分割点计算 left1right1left2right2,然后调整分割点以满足以下条件:

      • left1 和 left2 的最大值要小于等于 right1 和 right2 的最小值。
    4. 如果分割点满足条件,则根据总元素个数的奇偶性计算中位数。

    5. 如果分割点不满足条件,则根据条件调整分割点,继续二分查找。

C 语言实现

#include <stdio.h>
#include <limits.h>double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size) {if (nums1Size > nums2Size) {int* tempArr = nums1;nums1 = nums2;nums2 = tempArr;int tempSize = nums1Size;nums1Size = nums2Size;nums2Size = tempSize;}int imin = 0, imax = nums1Size, half_len = (nums1Size + nums2Size + 1) / 2;while (imin <= imax) {int i = (imin + imax) / 2;int j = half_len - i;if (i < nums1Size && nums2[j - 1] > nums1[i]) {imin = i + 1;} else if (i > 0 && nums1[i - 1] > nums2[j]) {imax = i - 1;} else {int max_of_left, min_of_right;if (i == 0) max_of_left = nums2[j - 1];else if (j == 0) max_of_left = nums1[i - 1];else max_of_left = (nums1[i - 1] > nums2[j - 1]) ? nums1[i - 1] : nums2[j - 1];if ((nums1Size + nums2Size) % 2 == 1) return max_of_left;if (i == nums1Size) min_of_right = nums2[j];else if (j == nums2Size) min_of_right = nums1[i];else min_of_right = (nums1[i] < nums2[j]) ? nums1[i] : nums2[j];return (max_of_left + min_of_right) / 2.0;}}return 0.0;
}

Java 实现

public class Solution {public double findMedianSortedArrays(int[] nums1, int[] nums2) {if (nums1.length > nums2.length) {int[] temp = nums1;nums1 = nums2;nums2 = temp;}int x = nums1.length;int y = nums2.length;int low = 0, high = x;while (low <= high) {int partitionX = (low + high) / 2;int partitionY = (x + y + 1) / 2 - partitionX;int maxX = (partitionX == 0) ? Integer.MIN_VALUE : nums1[partitionX - 1];int minX = (partitionX == x) ? Integer.MAX_VALUE : nums1[partitionX];int maxY = (partitionY == 0) ? Integer.MIN_VALUE : nums2[partitionY - 1];int minY = (partitionY == y) ? Integer.MAX_VALUE : nums2[partitionY];if (maxX <= minY && maxY <= minX) {if ((x + y) % 2 == 0) {return (Math.max(maxX, maxY) + Math.min(minX, minY)) / 2.0;} else {return Math.max(maxX, maxY);}} else if (maxX > minY) {high = partitionX - 1;} else {low = partitionX + 1;}}throw new IllegalArgumentException("Input arrays are not sorted.");}
}

Python 实现

def findMedianSortedArrays(nums1, nums2):if len(nums1) > len(nums2):nums1, nums2 = nums2, nums1x, y = len(nums1), len(nums2)low, high = 0, xwhile low <= high:partitionX = (low + high) // 2partitionY = (x + y + 1) // 2 - partitionXmaxX = float('-inf') if partitionX == 0 else nums1[partitionX - 1]minX = float('inf') if partitionX == x else nums1[partitionX]maxY = float('-inf') if partitionY == 0 else nums2[partitionY - 1]minY = float('inf') if partitionY == y else nums2[partitionY]if maxX <= minY and maxY <= minX:if (x + y) % 2 == 0:return (max(maxX, maxY) + min(minX, minY)) / 2.0else:return max(maxX, maxY)elif maxX > minY:high = partitionX - 1else:low = partitionX + 1raise ValueError("Input arrays are not sorted.")

时间复杂度

所有三种实现的方法的时间复杂度都是 (O(\log(\min(m, n)))),其中 (m) 和 (n) 分别是两个数组的长度。这是因为我们主要是在较短的数组上进行二分查找。

这篇关于第四题:求两个有序数组的中位数(Median of Two Sorted Arrays)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1102605

相关文章

Java 字符数组转字符串的常用方法

《Java字符数组转字符串的常用方法》文章总结了在Java中将字符数组转换为字符串的几种常用方法,包括使用String构造函数、String.valueOf()方法、StringBuilder以及A... 目录1. 使用String构造函数1.1 基本转换方法1.2 注意事项2. 使用String.valu

JAVA中整型数组、字符串数组、整型数和字符串 的创建与转换的方法

《JAVA中整型数组、字符串数组、整型数和字符串的创建与转换的方法》本文介绍了Java中字符串、字符数组和整型数组的创建方法,以及它们之间的转换方法,还详细讲解了字符串中的一些常用方法,如index... 目录一、字符串、字符数组和整型数组的创建1、字符串的创建方法1.1 通过引用字符数组来创建字符串1.2

锐捷和腾达哪个好? 两个品牌路由器对比分析

《锐捷和腾达哪个好?两个品牌路由器对比分析》在选择路由器时,Tenda和锐捷都是备受关注的品牌,各自有独特的产品特点和市场定位,选择哪个品牌的路由器更合适,实际上取决于你的具体需求和使用场景,我们从... 在选购路由器时,锐捷和腾达都是市场上备受关注的品牌,但它们的定位和特点却有所不同。锐捷更偏向企业级和专

基于Redis有序集合实现滑动窗口限流的步骤

《基于Redis有序集合实现滑动窗口限流的步骤》滑动窗口算法是一种基于时间窗口的限流算法,通过动态地滑动窗口,可以动态调整限流的速率,Redis有序集合可以用来实现滑动窗口限流,本文介绍基于Redis... 滑动窗口算法是一种基于时间窗口的限流算法,它将时间划分为若干个固定大小的窗口,每个窗口内记录了该时间

vue如何监听对象或者数组某个属性的变化详解

《vue如何监听对象或者数组某个属性的变化详解》这篇文章主要给大家介绍了关于vue如何监听对象或者数组某个属性的变化,在Vue.js中可以通过watch监听属性变化并动态修改其他属性的值,watch通... 目录前言用watch监听深度监听使用计算属性watch和计算属性的区别在vue 3中使用watchE

hdu2241(二分+合并数组)

题意:判断是否存在a+b+c = x,a,b,c分别属于集合A,B,C 如果用暴力会超时,所以这里用到了数组合并,将b,c数组合并成d,d数组存的是b,c数组元素的和,然后对d数组进行二分就可以了 代码如下(附注释): #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<que

hdu 1166 敌兵布阵(树状数组 or 线段树)

题意是求一个线段的和,在线段上可以进行加减的修改。 树状数组的模板题。 代码: #include <stdio.h>#include <string.h>const int maxn = 50000 + 1;int c[maxn];int n;int lowbit(int x){return x & -x;}void add(int x, int num){while

leetcode-23Merge k Sorted Lists

带头结点。 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) { val = x; }* }*/public class Solution {public ListNode mergeKLists

两个月冲刺软考——访问位与修改位的题型(淘汰哪一页);内聚的类型;关于码制的知识点;地址映射的相关内容

1.访问位与修改位的题型(淘汰哪一页) 访问位:为1时表示在内存期间被访问过,为0时表示未被访问;修改位:为1时表示该页面自从被装入内存后被修改过,为0时表示未修改过。 置换页面时,最先置换访问位和修改位为00的,其次是01(没被访问但被修改过)的,之后是10(被访问了但没被修改过),最后是11。 2.内聚的类型 功能内聚:完成一个单一功能,各个部分协同工作,缺一不可。 顺序内聚:

C语言:柔性数组

数组定义 柔性数组 err int arr[0] = {0}; // ERROR 柔性数组 // 常见struct Test{int len;char arr[1024];} // 柔性数组struct Test{int len;char arr[0];}struct Test *t;t = malloc(sizeof(Test) + 11);strcpy(t->arr,