1. 程式人生 > >求兩個已排序(升序)等長的整數陣列所有元素的中位數

求兩個已排序(升序)等長的整數陣列所有元素的中位數

     演算法課的題目,給定兩個整數陣列x[], y[],兩個陣列已被排序(升序),陣列長度都是n,求這2n個數的中位數。

     最容易想到的是,新建立以個數組 z[2n],將x[],y[]的所有元素排序放入,然後取中間兩個數,不過當陣列很大時,效率不行啊。<^_^>,不僅空間複雜度很大,重新排序的話也要不少時間.

    分析:因為兩個陣列已經排序了,可以找找規律嗎?這樣就可以直接找出和中位數有關的幾個元素(兩個???)。若x的最大元素小於y的最小元素(或者y的最大元素小於x的最小元素),答案就出來了。如果把x看成是從x[0]到x[maxIndex]的連續區間(數抽???),y也是如此。那麼,兩個區間可能有重疊部分,可能完全不重疊,也可能大區間完全包含小區間......

    雖然最終確定應該借鑑二分搜尋的思想,但是有很多問題不會證明,只是從同學那裡知道應該這樣,呵呵。以後再試試證明吧,數學沒學好啊。。。。

#include <stdio.h>
#include <stdlib.h>


/* 比較兩個整數[ x and y]大小的函式.
 *   Return values:
 *       1: x > y.
 *       0: x == y.
 *       -1: x < y.
 * */
int compare(int x, int y)
{
    return (x > y) ? 1 : ( (x == y) ? 0 : -1);
}


//這是個簡單的排序函式, 你懂得<^_^>.
void sortFour(int a[], int n)
{
    int i, j, temp;
    for (i = 0; i < n; ++i)
    {
        for (j = i + 1; j < n; ++j)
        {
            if (a[i] > a[j])
            {
                temp = a[i];
                a[i] = a[j];
                a[j] = temp;
            }
        }
    }
}
/* 這個才是主角, 給定兩個長度為(maxIndex + 1)的陣列x[], y[],
 * 兩個陣列已被排序(升序). 使用二分的思想求兩個陣列所有元素的中位數.
 *   因為總元素數為偶數,故中位數由中間的兩個數合成。這兩個數可能位
 *   於同一個數組裡,故每個陣列二分時,最後保留兩個元素,一共
 *   四個,再排序,取中間兩個。
 * */
double findMedian(const int x[], const int y[], int maxIndex)
{
    if (maxIndex < 0)
    {
        //老問題,檢查一下
        puts("Wrong length of array!");
        exit(-1);
    }
    int Lx, Ly, Rx, Ry, Mx, My;
    Lx = Ly = 0;
    Rx = Ry = maxIndex;
    
    while ( Lx < (Rx - 1) )//當只剩兩個(嚴格的說,包括少於兩個的情況,
                           //額,那就是一個嘍)元素時,就跳出. 
    {
        Mx = (Lx + Rx) >> 1;
        /* * * * * * * * * * * * * * * * * * * *
         * 這裡有個問題是,當區間長度是偶數時,
         * 比如,8,則Mx = 4,此時這個二分的中
         * 點也可以是5,對y[]也是一樣。但是因為
         * 我們是從兩邊"逼近中間",所以若x是從左
         * 逼近,那麼y就是從右邊逼近,所以應該My = 5,
         * 而不是4,否則得不到正確的結果.
         * (有點像對稱的意思,大概就這樣,
         * 現在我還不會證明,見諒<^_^>)
         * * * * * * * * * * * * * * * * * * * */
        if ( ((Ry - Ly + 1) & 1))
        {
            My = (Ly + Ry) >> 1;
        }
        else
        { 
            My = (Ly + Ry + 1) >> 1;
        }
        switch( compare(x[Mx], y[My]) )
        {
            case 0:
            case 1:
                Rx = Mx;
                Ly = My;
                break;
            case -1:
                Lx = Mx;
                Ry = My;
        }
    }

    //最後的四個數,
    int a[4];
    a[0] = x[Lx];
    a[1] = x[Rx];
    a[2] = y[Ly];
    a[3] = y[Ry];

    sortFour(a, 4);//排個序
    
    //結果用double 存放,保留小數.
    double result = (double)(a[1] + a[2]) / 2;
    
    return result;
}


//Application start.
int main(void)
{
    int n = 0;
    int i;
    double result;
    do
    {
        printf("Input the length of array:");
        fflush(stdin);
        scanf("%d", &n);
    } while (n < 1);

    int num_1[n];
    int num_2[n];

    printf("Inpuut the data of group 1:");
    fflush(stdin);
    for (i = 0; i < n; ++i)
    {
        scanf("%d", num_1 + i);
    }

    printf("Inpuut the data of group 2:");
    fflush(stdin);
    for (i = 0; i < n; ++i)
    {
        scanf("%d", num_2 + i);
    }

    result = findMedian(num_1, num_2, n - 1);
    printf("the result is : %.2f", result);

    getch();
    return 0;
}

相關推薦

排序(升序)整數陣列所有元素位數

     演算法課的題目,給定兩個整數陣列x[], y[],兩個陣列已被排序(升序),陣列長度都是n,求這2n個數的中位數。      最容易想到的是,新建立以個數組 z[2n],將x[],y[]的所有元素排序放入,然後取中間兩個數,不過當陣列很大時,效率不行啊。<^

演算法5:排序陣列的交集和並集

問題描述 求兩個已排序資料的交集和並集,要求時間複雜度為O(m+n). 解題思路 A陣列和B陣列,A陣列大小為m,B陣列大小為n。 1、查詢B陣列的每個成員是否在A陣列中,時間複雜度為O(mn) 2、由於A和B陣列都是有序陣列,使用二分法查詢B陣列

排序陣列所有元素的第K大(小)

1.reference 2.解題思路 以下均假設A[0…m-1],B[0…n-1]; 1)O(n) 假設A,B均以降序排列,宣告兩個指標p,q。p指向A[0], q指向B[0]。再來一個count=0,用來表示當前已經到第count大了。然後指標

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 sorted arrays. The overall run

用O(lgn)時間排序陣列位數

相關問題: 設 x[1..n]和Y[1..n]為兩個陣列,每個都包含n個已排序的數。給出一個求陣列X和Y中所有2n個元素的中位數的O(lgn)時間的演算法。 思考過程:         開始我想把兩個陣列X與Y放入到一個數組Z中,對Z進行排序,這樣Z的中位數易求。但是有2點

公共字串的最公共子串(C++)

思路: 1.按兩字串長度,兩層迴圈 2.每一次迴圈找出潛在的公共字串 (比較笨的方法,但比較好用,也很清楚,程式碼如下) #include<iostream> #include<stdio.h> #include<algorithm>

LeetCode 21 Merge Two Sorted Lists(合併排序的連結串列)(Linked List)

翻譯 合併兩個排好序的連結串列,並返回這個新連結串列。 新連結串列應該由這兩個連結串列的頭部拼接而成。 原文 Merge two sorted linked lists and return it as a new list. The new

資料結構演算法題/排序陣列的交集和並集

兩個已排序陣列的交集和並集 問題: 給你兩個排序的陣列,求兩個陣列的交集。 比如: A = 1 3 4 5 7, B = 2 3 5 8 9, 那麼交集就是 3 5. 思路: 1. 每一次從B陣列中取一值,然後在A數組裡逐個比較,如果有相等的,則儲存。該演算法複雜度為 O(MN).

合併有序(升序)連結串列的操作!

問題:現有LA與LB兩個連結串列,已升序排列。將LA與LB合併後也按升序排列. 演算法1:在LB中分別取出它的結點,再分別與LA中的節點進行比較,找到位置後插入。但是這種演算法複雜度太大,假如LA與

排序的連結串列歸併成一個連結串列(C++面試題)

題目: 將兩個已經排好序的連結串列組合成一個排序的連結串列。 /* 歸併排序的思想 時間:2015年4月8日 19:59:02 */ #include <iostream> #include <cstdlib> using namespace

尋找排序陣列位數

給定兩個大小為 m 和 n 的有序陣列 nums1 和 nums2 。請找出這兩個有序陣列的中位數。要求演算法的時間複雜度為 O(log (m+n)) 。nums1 = [1, 3] nums2 = [2] 中位數是 2.0nums1 = [1, 2] nums2 = [3

升序序列的位數

1.        演算法要求 一個長度為L(L≥1)的升序序列S,處在第L / 2(若為小數則去掉小數後加1)個位置的數稱為S 的中位數。例如,若序列S1=(11,13,15,17,19),則S1 的中位數是15,兩個序列的中位數是含它們所有元素的升序序列的中位數。例

有序序列的位數

/*現有兩個等長的升序序列的序列A,B,試設計一個時間和空間都儘可能高效的演算法,找出兩個序列的中位數 演算法的基本思想是:分別求出兩個序列的中位數,即為a b,有下列三種情況 1:a=b;即a 為兩

有序陣列位數的logN演算法 分治法

http://blog.csdn.net/yangliuy/article/details/7194199 題目:有兩個長為n的非遞減陣列A和B,把B接在A的後面變成長為2n的陣列C。設計演算法求C的中位數(第n小數)。 思路:O(n)的演算法很容易找到,關鍵是用二

(java)排序陣列升序第K小的數

如題:求兩個排好序的陣列的第K個小的數 思路一:歸併兩個有序陣列,按照順序合併,最後找到第K-1位置的數。時間複雜度為O(N) 思路二:在技術部落格上看到更好的思路,時間複雜度是OLog(m+n); 第k小的數字為x,那麼陣列1一定有i個數字小於x,陣列2一定有j個數字小於

字符串的最公共子串——Java實現

求解 ont ins oid info ++ 題意 短字符串 clas 要求:求兩個字符串的最長公共子串,如“abcdefg”和“adefgwgeweg”的最長公共子串為“defg”(子串必須是連續的) public class Main03{ // 求解兩個字符號的最

《程式設計師程式碼面試指南》字串最公共子串

/** * 題目: * 給定兩個字串 str1 和 str2,返回兩個字串的最長公共子串。 *舉例: * str1 = "1AB2345CD",str2 = "12345EF",返回"2345"。 */ /** * 解答: * 經典動態規劃的方法可以做到時間複

python實現:字串的最公共子串

假設s1 = 'abcdef'  ,s2 = 'mcdea',建立一個(len(s1)+1) x (len(s2)+1)的陣列,如下如所示的一個二維陣列,程式碼的操作流程是: # -*- coding

分治法長度相同都按升序排列陣列位數

#include <iostream> using namespace std; void Mid(int a[],int aleft,int aright,int b[],int bleft,int bright) { double mid;

用字尾陣列字串的最公共子串

對於兩個字串,不好直接運用字尾陣列,所以我們可以把兩個子串串中間用一個在字串中不會出現的字元連線起 來,比如'$‘,計算字尾陣列,檢查字尾陣列中所有相鄰字尾。分屬於兩個字串的字尾的lcp的最大值就是答案。 因為字串的任何一個子串都是這個字串某個字尾的字首。求A和B 的最長公