Python 在不排序的情况下求数组中的中位数

百度/JD 面试题

题目:中位数就是一组数据从小到大排列后中间的那个数字。如果数组长度为偶数,那么中位数的值就是中间两个数字相加除以2,如果数组长度为奇数,那么就是中间那个数。

分析:采用类快速排序的方法,把问题转化为求一列数中第i小的数的问题,求中位数就是求一列数的第(len(arr)/2 + 1)小的数的问题)。

当使用依次类快速排序算法后,分割元素(Key)的下标为pos:

一次快拍后得到的是分割元素在最终排好序的数组中的Index.

(1)当pos > len(arr) / 2时,说明中位数在数组左半部分,在左半部分继续查找。

(2)当pos == len(arr) / 2,说明找到中位数arr[pos]。

(3)当pos < len(arr) / 2, 说明中位数在数组右半部分,在右半部分继续查找。

import os
import sys


def partition(arr, low, high):
	print '!'
	end = high

    #一般选取右侧值
	key = arr[high]
     
	while low < high:
		print low, high, arr[low], key, arr[high]

		while low < high and arr[low] < key:
			print 'low'+str(low)
			low = low + 1
		while low < high and arr[high] >= key:
			print 'high'+str(high)
			high = high - 1
        
        #进行一次交换
		if low < high:
			arr[low], arr[high] = arr[high], arr[low]
		print arr

	#将Key值放回数组,使得左侧都比key小,右侧都比Key大
    arr[high], arr[end] = arr[end], arr[high]

	#返回选取的key值在排序后的数组的坐标。这个坐标也是其在最终排好序的数组中的坐标
    #一次快排序的实质就是确定选取的Key值在最终数组中的位置。
	return high


def getMid(arr):
    start = 0
    end = len(arr) - 1
    
    #如果是奇数列,则是中间值
    #如果是偶数列,则是 中间两个值,即 (n/2)-1, n/2
    if len(arr) % 2 == 1:
        mid = len(arr)/2
    else:
        mid = len(arr)/2 - 1

    print 'mid is ' + str(mid)

    while start < end:
    	print start,end
        
        #经过一次排序,可以知道正确的Key值所处的范围
        #在这个范围内,选取一个进行快排序,得到它在最终数组里的index值,重复。
    	pos = partition(arr, start, end)
        
        #只要选取index,就能把这个数找出来,这里是n/2, 也可以是任意值。
        if pos == mid:
        	break
        elif pos > mid:
            end = pos - 1 
        else:
            start = pos + 1    
 
    return arr[pos]

if __name__ == "__main__":
    arr = [7,3,4,5,6,7,7,7,7,1,1]
    print(arr)
    a = getMid(arr)
    print a

以上默认此数组序列长度为奇数,如果为偶数就是调用上述方法两次查找中间的两个数,再求平均。

 

你可能感兴趣的:(算法)