IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 【算法】Median of Two Sorted Arrays -> 正文阅读

[数据结构与算法]【算法】Median of Two Sorted Arrays

1. 概述

LeetCode4: https://leetcode.com/problems/median-of-two-sorted-arrays/

求两个有序数组的中位数,要求时间复杂度为 O(log(m + n))


2. 思路分析

很显然,这题应该采用二分查找的思路才能满足时间复杂度 O(log(m + n)) 的要求。

首先需要明确中位数的定义,如果两个数组的长度之和为奇数,那么中位数就是最中间的那个值;如果是偶数,那么中位数应该是最中间的两个数的平均值。一个小trick,(m + n + 1) / 2(m + n + 2) / 2 的下标就是两个数组的中间的位置,如果数组长度之和为奇数,那么这两个得出的是同一个数,如果为偶数,那么分别指向中间位置的两个数。

那么求中位数这个问题就变成了求两个数组中的第 (m + n + 1) / 2 大的数和 (m + n + 2) / 2 大的数。那么就需要一个求第K大的函数。


采用二分思路每次淘汰 k / 2 的数

找出nums1中第k/2大的数midval1和nums2中第k/2大的数midVal2,如果

  1. midVal1 <= midVal2:那么nums1中的前k/2个数就可以被丢弃了,因为第k大的数不可能在nums1的前k/2个数中;
  2. midVal1 > midVal2:那么同样,nums2中的前k/2个数就可以被丢弃了。

当然,在比较的过程中需要考虑是否越界的问题:

  1. 如果nums1中数的个数根本就不够 k/2 个,那么就应该保存nums1中的数,而去淘汰nums2中的数(因为第k大的数不可能在nums2的前k/2个数中的,因为nums1中不足k/2个数。那么我们就可以淘汰nums2的前k/2个数),那么我们可以将midVal1设置为INT_MAX以使其比midVal2大,这样就不会淘汰nums1中的数了;
  2. nums2同理。

那么会不会出现nums1和nums2都没有k/2个数的情况呢?在这里的情况是不可能的,因为是求的中位数,那么nums1和nums2中至少有一个包含的数大于等于k/2。


3. 代码和测试结果

Java

package cn.pku.edu.algorithm.leetcode.day01;

/**
 * @author allen
 * @date 2022/9/18
 */
public class LeetCode4 {
    public static void main(String[] args) {
        Solution solution = new Solution();
        int[] nums1 = {1, 3}, nums2 = {2, 4};
        double res = solution.findMedianSortedArrays(nums1, nums2);
        System.out.println(res);
    }
}

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int left = (nums1.length + nums2.length + 1) / 2;
        int right = (nums1.length + nums2.length + 2) / 2;

        if (left != right) {
            double median1 = findKth(nums1, 0, nums2, 0, left);
            double median2 = findKth(nums1, 0, nums2, 0, right);
            return (median1 + median2) / 2;
        } else {
            return findKth(nums1, 0, nums2, 0, left);
        }
    }

    /**
     * find the k-th element among two sorted arrays
     */
    private double findKth(int[] nums1, int i, int[] nums2, int j, int k) {
        if (i >= nums1.length) return nums2[j + k - 1];
        if (j >= nums2.length) return nums1[i + k - 1];
        if (k == 1) return Math.min(nums1[i], nums2[j]);
        // 取第k/2大的数,如果长度不够,则取整数的最大值,防止被去掉
        int midVal1 = (i + k / 2 - 1 < nums1.length)? nums1[i + k / 2 - 1] : Integer.MAX_VALUE;
        int midVal2 = (j + k / 2 - 1 < nums2.length)? nums2[j + k / 2 - 1] : Integer.MAX_VALUE;
        if (midVal1 <= midVal2) {
            return findKth(nums1, i + k / 2, nums2, j, k - k / 2);
        } else {
            return findKth(nums1, i, nums2, j + k / 2, k - k / 2);
        }
    }
}

C++

#include <iostream>
#include <vector>

using namespace std;

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int left = (nums1.size() + nums2.size() + 1) / 2;
        int right = (nums1.size() + nums2.size() + 2) / 2;
        if (left == right) {
            return findKth(nums1, 0, nums2, 0, left);
        } else {
            double median1 = findKth(nums1, 0, nums2, 0, left);
            double median2 = findKth(nums1, 0, nums2, 0, right);
            return (median1 + median2) / 2;
        }
    }

    double findKth(vector<int>& nums1, int i, vector<int>& nums2, int j, int k) {
        if (i >= nums1.size()) return nums2[j + k - 1];
        if (j >= nums2.size()) return nums1[i + k - 1];
        if (k == 1) return min(nums1[i], nums2[j]);
        int midVal1 = (i + k / 2 - 1 < nums1.size())? nums1[i + k / 2 - 1] : INT_MAX;
        int midVal2 = (j + k / 2 - 1 < nums2.size())? nums2[j + k / 2 - 1] : INT_MAX;
        if (midVal1 <= midVal2) {
            return findKth(nums1, i + k / 2, nums2, j, k - k / 2);
        } else {
            return findKth(nums1, i, nums2, j + k / 2, k - k / 2);
        }
    }
};

int main() {
    vector<int> nums1 = {1, 3}, nums2 = {2, 4};
    double res = Solution().findMedianSortedArrays(nums1, nums2);
    cout << res << endl;
    return 0;
}

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-09-21 00:52:38  更:2022-09-21 00:54:17 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 21:14:50-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码