您的位置:首页 > 其它

求俩个有序序列的中位数 ,和求众数问题

2013-04-15 19:27 375 查看
2010-03-31 10:43

google笔试题两个n维数组logn求中位数问题

两个n维数组,已排序,为升序。设计算法求2n的数中第n大的数。要求分析时间和空间复杂度。
比较两个有序表各自的中位数 a,b 假设 a>=b,那么这2n个数的中位数一定不在第一个序列>a的那部分上,因为第一个序列中有n/2-1个数比a小,第二个序列中至少有n/2个数比a小(a>=b),同理,中位数一定不在第二个序列<b的那部分。这样每个序列中各排除了n/2, 于是变为了n/2的两个有序序列中求中位数。当序列长度为一时,较小数即为所求中位数。

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

#define N 5

#define MAX(a,b) (a)>(b)?(a):(b)

void print_arrat(int A[], int n)

{

int i;

for(i=0;i<n;i++)

printf("%d\t",A[i]);

printf("\n");

}

void swap(int* a, int* b)

{

int tmp = *a;

*a = *b;

*b = tmp;

}

int partition(int A[], int start, int end)

{

int x = A[end];

int i = start-1;

int j = start;

for(;j<end;j++)

{

if(A[j]<x)

{

i++;

swap(A+i, A+j);

}

}

swap(A+i+1, A+end);

return i+1;

}

void quick_sort(int A[], int start, int end)

{

if(start<end)

{

int q = partition(A, start, end);

quick_sort(A, start, q-1);

quick_sort(A, q+1, end);

}

}

int count_mid_n(int A[],int a_start,int a_end,int B[],int b_start,int b_end)

{

int ret = 0;

if((a_start==a_end)||(b_start==b_end))

{

printf("min %d %d\n", A[a_start], B[b_start]);

ret = MAX(A[a_start], B[b_start]);

printf("ret is %d\n", ret);

return ret;

}

else

{

int a_mid = (a_start+a_end)/2;

int b_mid = (b_start+b_end)/2;

printf("a_mid is %d, b_mid is %d\n", A[a_mid], B[b_mid]);

if(A[a_mid]>B[b_mid])

return count_mid_n(A, a_start,a_mid,B,b_mid,b_end);

else if(A[a_mid]<B[b_mid])

return count_mid_n(A, a_mid,a_end,B,b_start,b_mid);

else

{

ret = A[a_mid];

return ret;

}

}

}

int main(int argc, char *argv[])

{

int i;

int ret;

srand((unsigned int)time(NULL));

int A
;

int B
;

for(i=0;i<N;i++)

A[i] = rand()%100;

for(i=0;i<N;i++)

B[i] = rand()%100;

quick_sort(A, 0, N-1);

quick_sort(B, 0, N-1);

printf("array A is:\n");

print_arrat(A,N);

printf("array B is:\n");

print_arrat(B,N);

ret = count_mid_n(A,0,N-1,B,0,N-1);

printf("mid of 2n is: %d\n", ret);

system("PAUSE");

return 0;

}

#include <iostream>

#include <time.h>

using namespace std;

//Mode是从QuickSort得到

void Mode(int *, int, int, int *);

int Partition(int *, int, int);

//top是下一个众数的下标,top-1是当前众数的下标

//top和Frequence是全局变量,任何一处的赋值都会改变他们的值

//全局变量不作为函数参数,而是在函数内部直接使用

static int top = 0;

//Frequence记录众数的重数

static int Frequence = 0;

int main()

{

//生成随机数组

int n = 100;

int * nData = new int
;

srand(time(0));

for (int i=0;i<n;i++)

nData [i] = 1 + rand()%n;  //随机域为[1,n];

//打印

cout << "随机数组:" << endl;

for(int j=0;j<n;j++)

cout << nData[j] << "  ";

cout << endl;

//数组nVal存储众数的值,只在[0,top-1]位置存放众数,top-1之后无效

int * nVal = new int
;

//求众数及重数

Mode(nData,0,n-1, nVal);

//输出

cout<<"众数:  ";

for (int k=0;k<top;k++)

cout<<nVal[k]<<" ";

cout << endl;

cout << "重数:    " << Frequence << endl;

delete [] nData;

delete [] nVal;

return 0;

}

//求数组nData的众数

void Mode(int * nData, int left, int right,int * nVal)

{

int X = nData[left];

if(left<right)

{

//将小于X的放于其左(未排序),大于X的放于其右(未排序),并返回X在数组中的最终位置。

int i = Partition(nData,left,right);

//统计X出现的次数

int T=0;

for(int j = left; j <= right; j++)

{

if(nData[j]==X)

T++;

}

if(T==Frequence)

{

nVal[top] = nData[i];

top++;

//Frequence = T;

}

else if (T>Frequence)

{

nVal[0] = nData[i];

top=1;

Frequence = T;

}

if((i-left)>=T)

Mode(nData,left,i-1,nVal);

if((right-i)>=T)

Mode(nData,i+1,right,nVal);

}

}

//将小于nData[left]的元素放在nData[left]左边,大于nData[left]的元素放在nData[left]右边

//并返回nData[left]的最终位置

//Partition()并没有进行排序,只是分区

int Partition(int * nData, int left, int right)

{

int i=left, j=right+1;

int x = nData[left];

while(true)

{

while(nData[++i] < x);

while(nData[--j] > x);

if(i >= j) break;

int temp = nData[i];

nData[i] = nData[j];

nData[j] = temp;

// Swap(nData[i],nData[j]);

}

nData[left] = nData[j];

nData[j] = x;

return j;

}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: