#include <iostream>
using namespace std;

/*函数作用:取待排序序列中low、mid、high三个位置上数据,选取他们中间的那个数据作为枢轴*/
int median(int arr[], int b[], int len1, int low, int high) {
	int mid = low + ((high - low) >> 1); //计算数组中间的元素的下标

	int &lowData = low >= len1 ? b[low - len1] : arr[low];
	int &midData = mid >= len1 ? b[mid - len1] : arr[mid];
	int &highData = high >= len1 ? b[high - len1] : arr[high];
	//使用三数取中法选择枢轴
	if (midData > highData) //目标: arr[mid] <= arr[high]
			{
		swap(midData, highData);
	}
	if (lowData > highData) //目标: arr[low] <= arr[high]
			{
		swap(lowData, highData);
	}
	if (midData > lowData) //目标: arr[low] >= arr[mid]
			{
		swap(midData, lowData);
	}
	//此时,arr[mid] <= arr[low] <= arr[high]
	return lowData;
	//low的位置上保存这三个位置中间的值
	//分割时可以直接使用low位置的元素作为枢轴,而不用改变分割函数了
}

int kth_elem(int a[], int b[], int len1, int low, int high, int k) {
	int pivot = median(a, b, len1, low, high);

	//要么是选取数组中中位数作为枢纽元,保证最坏情况下,依然为线性O(N)的平均时间复杂度。
	int low_temp = low;
	int high_temp = high;
	while (low < high) {
		int tmp = high >= len1 ? b[high - len1] : a[high];
		while (low < high && tmp >= pivot) {
			--high;
			tmp = high >= len1 ? b[high - len1] : a[high];
		}
		if (low >= len1) {
			b[low - len1] = tmp;
		} else {
			a[low] = tmp;
		}

		int tmp1 = low >= len1 ? b[low - len1] : a[low];
		while (low < high && tmp1 < pivot) {
			++low;
			tmp1 = low >= len1 ? b[low - len1] : a[low];
		}
		if (high >= len1) {
			b[high - len1] = tmp1;
		} else {
			a[high] = tmp1;
		}
	}

	if (low >= len1) {
		b[low - len1] = pivot;
	} else {
		a[low] = pivot;
	}

	//以下就是主要思想中所述的内容
	if (low == k - 1) {
		if (low >= len1) {
			return b[low - len1];
		}
		return a[low];
	} else if (low > k - 1)
		return kth_elem(a, b, len1, low_temp, low - 1, k);
	else
		return kth_elem(a, b, len1, low + 1, high_temp, k);
}

void printArray(int* arr, int len) {
	if (!arr) {
		return;
	}
	for (int i = 0; i < len; ++i) {
		cout << arr[i] << " ";
	}
	cout << endl;
}

void print2SortedArray(int* a, int* b, int len1, int len2) {
	int* arr = new int[len1 + len2];
	for (int i = 0; i < len1; ++i) {
		arr[i] = a[i];
	}
	for (int i = len1, j = 0; j < len2; ++i, j++) {
		arr[i] = b[j];
	}
	sort(arr, arr + len1 + len2);
	printArray(arr, len1 + len2);
	delete arr;
}

int main() {
	int arr1[] = { 2, 12, 5, 10, 43, 24, 33, 4 };
	int arr2[] = { 10, 23, 41, 70, 84, 29, 6 };

	int len1 = sizeof(arr1) / sizeof(int);
	int len2 = sizeof(arr2) / sizeof(int);

	print2SortedArray(arr1, arr2, len1, len2);

	int mid1 = (len1 + len2) / 2 + 1;
	int mid2 = (len1 + len2) % 2 == 0 ? mid1 - 1 : mid1;

	int midData1 = kth_elem(arr1, arr2, len1, 0, len1 + len2 - 1, mid1);
	int midData2 = kth_elem(arr1, arr2, len1, 0, len1 + len2 - 1, mid2);

//	cout << midData1 << ',' << midData2 << endl;
	cout << "中位数: " << (midData1 + midData2) / 2 << endl;
	return 0;
}

两个无序数组分别叫A和B,长度分别是m和n,求中位数,要求时间复杂度O(m+n),空间复杂度O(1) 。的更多相关文章

  1. 已知大小分别为m、n的两个无序数组A、B和一个常数c,求满足A[i]+B[j]=c的所有A[i]和B[j]

    方法一:枚举法.该方法是最容易.也是最简单的方法,枚举出数组A和数组B中所有的元素对,判断其和是否为c,如果是,则输出. 方法二:排序+二分查找法.首先,对两个数组中长度较大数组,不妨设为A,排序:然 ...

  2. 从0打卡leetcode之day 5 ---两个排序数组的中位数

    前言 我靠,才坚持了四天,就差点不想坚持了.不行啊,我得把leetcode上的题给刷完,不然怕是不好进入bat的大门. 题目描述 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2 . ...

  3. 如何寻找无序数组中的第K大元素?

    如何寻找无序数组中的第K大元素? 有这样一个算法题:有一个无序数组,要求找出数组中的第K大元素.比如给定的无序数组如下所示: 如果k=6,也就是要寻找第6大的元素,很显然,数组中第一大元素是24,第二 ...

  4. 对无序数组的并发搜索的java实现

    对无序数组的并发搜索的实现可以充分的用到多cpu的优势 一种简单的策略是将原始数组按照期望的线程数进行分割,如果我们计划使用两个线程进行搜索,就可以把一个数组分成两个,每个线程各自独立的搜索,当其中有 ...

  5. 从长度为 M 的无序数组中,找出N个最小的数

    从长度为 M 的无序数组中,找出 N个最小的数 在一组长度为 n 的无序的数组中,取最小的 m个数(m < n), 要求时间复杂度 O(m * n) 网易有道面试题 const minTopK ...

  6. 无序数组求第K大的数

    问题描述 无序数组求第K大的数,其中K从1开始算. 例如:[0,3,1,8,5,2]这个数组,第2大的数是5 OJ可参考:LeetCode_0215_KthLargestElementInAnArra ...

  7. [LeetCode] Median of Two Sorted Arrays 两个有序数组的中位数

    There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two ...

  8. 取两个String数组的交集

    import org.testng.annotations.Test; import java.util.HashMap; import java.util.LinkedList; import ja ...

  9. 有1,2,3一直到n的无序数组,排序

    题目:有1,2,3,..n 的无序整数数组,求排序算法.要求时间复杂度 O(n), 空间复杂度O(1). 分析:对于一般数组的排序显然 O(n) 是无法完成的. 既然题目这样要求,肯定原先的数组有一定 ...

随机推荐

  1. java 反射(Reflection)

    看了很多关于java 反射的文章,自己把所看到的总结一下.对自己,对他人或多或少有帮助吧. Java Reflection是什么? 首先来看看官方文档Oracle里面对Reflection的描述: R ...

  2. mysql 免安装与 忘记root密码 密码过期

    免安装: 参考 :https://blog.csdn.net/werwqerwerwer/article/details/52919939 注:别忘了配置环境变量   忘记root密码解决办法: 1. ...

  3. spring data jpa 组合条件查询封装

    /** * 定义一个查询条件容器 * @author lee * * @param <T> */ public class Criteria<T> implements Spe ...

  4. [AtCoder arc090F]Number of Digits

    Description 题库链接 记 \(d\) 在十进制下的位数为 \(f(d)\) .给出询问 \(S\) ,求有多少对 \((l,r)\) 使得 \[\sum_{i=l}^r f(i)=S\] ...

  5. [USACO14DEC]驮运Piggy Back

    题目描述 Bessie 和 Elsie在不同的区域放牧,他们希望花费最小的能量返回谷仓.从一个区域走到一个相连区域,Bessie要花费B单位的能量,Elsie要花费E单位的能量. 如果某次他们两走到同 ...

  6. bzoj 4545: DQS的trie

    Description DQS的自家阳台上种着一棵颗粒饱满.颜色纯正的trie. DQS的trie非常的奇特,它初始有n0个节点,n0-1条边,每条边上有一个字符.并且,它拥有极强的生长力:某个i时刻 ...

  7. bzoj 2555: SubString

    Description 懒得写背景了,给你一个字符串init,要求你支持两个操作 (1):在当前字符串的后面插入一个字符串 (2):询问字符串s在当前字符串中出现了几次?(作为连续子串) 你必须在线支 ...

  8. 笔记8 AOP练习2

    场景描述: 一张唱片有好多磁道,假设每个磁道只有一首歌,现在需要记录每首歌的播放次数,然后输出. 主要业务:歌曲播放 辅助功能:记录播放次数(切面) 1.创建唱片接口,CompactDiscs.jav ...

  9. React 深入系列4:组件的生命周期

    文:徐超,<React进阶之路>作者 授权发布,转载请注明作者及出处 React 深入系列4:组件的生命周期 React 深入系列,深入讲解了React中的重点概念.特性和模式等,旨在帮助 ...

  10. 第一次C语言作业

    1. 求圆的面积和周长 输入圆的半径,求圆的周长和面积 流程图 测试结果: 实验问题:1.加号输入到引号内部导致运算终止 解决办法:通过改正加号位置是算法正确并继续运行 2判断闰年 输入一个四位年份, ...