leetcode题目4.寻找两个有序数组的中位数(困难)
题目描述:
给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。
请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。
你可以假设 nums1 和 nums2 不会同时为空。
示例 1:
nums1 = [1, 3]
nums2 = [2]
则中位数是 2.0
示例 2:
nums1 = [1, 2]
nums2 = [3, 4]
则中位数是 (2 + 3)/2 = 2.5
解法一:虽然不符合时间复杂度要求,但是为了说明一下思路,还是cover一下,本地调试和提交都通过了,貌似leetcode缺少复杂度分析机制。
思路:两个排好序的数组,将两个数组合并成一个有序数组,若大数组的长度为奇数,则中位数为大数组中间的那个数,否则中位数为索引值分别是(0+arr.length)和(0+arr.length+1)之和的平均值
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int m = nums1.length;
int n = nums2.length;
return getMedian(nums1,m,nums2,n);
}
private double getMedian(int[] nums1, int m, int[] nums2, int n) {
int i = 0;
int j = 0;
int k = 0;
int[] resultArr = new int[m + n];
while (i < m && j < n) {
if (nums1[i] <= nums2[j]) {
resultArr[k++] = nums1[i++];
} else {
resultArr[k++] = nums2[j++];
}
}
while (i < m) {
resultArr[k++] = nums1[i++];
}
while (j < n) {
resultArr[k++] = nums2[j++];
}
int rn = k-1;
if (rn % 2 == 0) {
return resultArr[rn / 2] * 1.0 ;
} else {
return (resultArr[rn / 2] + resultArr[rn / 2 + 1]) * 1.0 / 2;
}
}
}
复杂度分析:
~时间复杂度:O(m+n)
~空间复杂度:O(m+n)
解法二:递归
思路:
两个有序数组求中位数,问题一般化为,求两个有序数组的第k个数,当k = (m+n)/2时为原问题的解。怎么求第k个数?分别求出第一个和第二个数组的第 k / 2个数 a 和 b,然后比较 a 和 b,当a < b ,说明第 k 个数位于 a数组的第 k / 2个数后半段,或者b数组的 第 k / 2 个数前半段,问题规模缩小了一半,然后递归处理就行。
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int m = nums1.length;
int n = nums2.length;
//当nums1数组为空的时候
if (m == 0) {
//两个数组的中位数完全取决于数组nums2了
if (n % 2 == 1) {
return nums2[n / 2] * 1.0;
}
return (nums2[n / 2] + nums2[n / 2 -1]) / 2.0;
}
//当nums2数组为空的时候
if (n == 0) {
if (m % 2 == 1) {
return nums1[m / 2] * 1.0;
}
return (nums1[m / 2] + nums1[m / 2 - 1]) / 2.0;
}
//大数组的总长度m+n
int total = m + n;
//数组长度为奇数,则在数组中寻找第total/2+1个数
if (total % 2 == 1) {
return find_kth(nums1, 0, nums2, 0, total / 2 + 1);
}
return (find_kth(nums1, 0, nums2, 0, total / 2) + find_kth(nums1, 0, nums2, 0, total / 2 + 1)) / 2.0;
}
private static double find_kth(int[] nums1, int a_begin, int[] nums2, int b_begin, int k) {
//当a_begin或b_begin超过数组长度,则第k个数为另外一个数组第k个数
if (a_begin >= nums1.length) {
return nums2[b_begin + k - 1];
}
//同理
if (b_begin >= nums2.length) {
return nums1[a_begin + k - 1];
}
//递归结束条件,每个数组中都找其第一个元素,使用递归,必须声明递归结束条件
if (k == 1) {
return Math.min(nums1[a_begin], nums2[b_begin]);
}
//定义mid_a和mid_b分别代表两个数组中的第k/2个数
int mid_a = Integer.MAX_VALUE;
int mid_b = Integer.MAX_VALUE;
if (a_begin + k / 2 - 1 < nums1.length) {
mid_a = nums1[a_begin + k / 2 - 1];
}
if (b_begin + k / 2 - 1 < nums2.length) {
mid_b = nums2[b_begin + k / 2 - 1];
}
//如果nums1数组的第 k / 2 个数小于nums2数组的第 k / 2 个数,表示总的第 k 个数位于 nums1的第k / 2个数的后半
// 段,或者是nums2的第 k / 2个数的前半段,由于范围缩小了 k / 2 个数,此时总的第 k 个数实际上等于新的范围内\
// 的第k - k / 2个数,依次递归
if (mid_a < mid_b) {
return find_kth(nums1, a_begin + k / 2, nums2, b_begin, k - k / 2);
}
return find_kth(nums1, a_begin, nums2, b_begin + k / 2, k - k / 2);
}
}
复杂度分析:
~时间复杂度: O(log(m+n))
leetcode题目4.寻找两个有序数组的中位数(困难)的更多相关文章
- LeetCode Golang 4. 寻找两个有序数组的中位数
4. 寻找两个有序数组的中位数 很明显我偷了懒, 没有给出正确的算法,因为官方的解法需要时间仔细看一下... func findMedianSortedArrays(nums1 []int, nums ...
- 【LeetCode】4. 寻找两个有序数组的中位数
给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 nums1 和 nums2 ...
- 【LeetCode 4】寻找两个有序数组的中位数
题目链接 [题解] 假设在两个有序的序列中找第k小的数字. 那么我们先定位第一个序列中的第k/2个数字(不足则取最边上的那个数字)记下标为i1 然后定位第二个序列中的第k/2个数字(同样不足则取最边上 ...
- Leetcode(4)寻找两个有序数组的中位数
Leetcode(4)寻找两个有序数组的中位数 [题目表述]: 给定两个大小为 m 和 n 的有序数组 nums1 和* nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O( ...
- Java实现 LeetCode 4 寻找两个有序数组的中位数
寻找两个有序数组的中位数 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 n ...
- 0004. 寻找两个有序数组的中位数(Java)
4. 寻找两个有序数组的中位数 https://leetcode-cn.com/problems/median-of-two-sorted-arrays/ 最简单的就是用最简单的,把两个数组分别抽出然 ...
- leetcode -- 寻找两个有序数组的中位数
题目: 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 nums1 和 nu ...
- 【LeetCode】寻找两个有序数组的中位数【性质分析+二分】
给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 nums1 和 nums2 ...
- LeetCode寻找两个有序数组的中位数
题目: 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 nums1 和 nu ...
随机推荐
- Qt常用快捷键
F1 查看帮助F2 跳转到函数定义(和Ctrl+鼠标左键一样的效果)Shift+F2 声明和定义之间切换F4 头文件和源文件之间切换Ctrl+1 ...
- 初识python之了解程序设计基本方法
对于用计算机解决一些问题,这里有一个程序设计的基本方法,主要分为六个步骤,其分析和实现过程如下: (1)分析问题:利用计算机解决问题需要结合计算机技术的发展水平和人类对问题的思考程度,在特定技术和社会 ...
- Java虚拟机-------垃圾回收机机制
概述 jvm中的堆图 在了解 垃圾回收器 之前,首先得了解一下垃圾回收器的几个名词. 1. 吞吐量CPU 用于运行用户代码的时间与 CPU 总消耗时间的比值.比如说虚拟机总运行了 100 分钟,用户代 ...
- Mac之常见问题
1. 在命令行下无法使用ll命令 需要设置命令的别名. 文件位置:-/.bash_profile source ~/.profile export PATH="/usr/local/opt/ ...
- 【2】Zookeeper安装
一.环境准备 Linux操作系统 Java运行环境(1.6或以上) 服务器列表: 配置主机名映射. vi /etc/hosts ##添加如下内容 168.5.7.75 server1 168.5.7. ...
- js对象的所有方法
Object构造方法 Object.assign() 将所有可枚举的自身属性的值从一个或多个源对象复制到目标对象. Object.create() 用指定的原型对象和属性创建一个新对象. Object ...
- Samba set of user authentication and file access rights
This series is compatible with Linux certification exam LPIC. A typical Linux user-level topics omit ...
- C# 获取 oracle 存储过程输出参数值
public bool QueueToRegister(string appointsId, string enrolDoctor) { using (OleDbConnection conn = n ...
- 单调队列优化&&P1886 滑动窗口题解
单调队列: 顾名思义,就是队列中元素是单调的(单增或者单减). 在某些问题中能够优化复杂度. 在dp问题中,有一个专题动态规划的单调队列优化,以后会更新(现在还是太菜了不会). 在你看到类似于滑动定长 ...
- 第二章 Vue快速入门--13 讲解v-model实现表单元素的数据双向绑定
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8&quo ...