有序陣列尋找中位數以及尋找K大元素

2022-08-23 08:27:08 字數 2497 閱讀 6383

問題描述:

兩個排序的陣列a和b分別含有m和n個數,找到兩個排序陣列的中位數,要求時間複雜度應為o(log (m+n))。轉化成找到兩個陣列的第k大數字進行解決

解題方法:

對於乙個長度為n的已排序數列a,若n為奇數,中位數為a[n / 2 + 1] , 若n為偶數,則中位數(a[n / 2] + a[n / 2 + 1]) / 2如果我們可以在兩個數列中求出第k小的元素,便可以解決該問題不妨設數列a元素個數為n,數列b元素個數為m,各自公升序排序,求第k小元素取a[k / 2] b[k / 2] 比較,如果 a[k / 2] > b[k / 2] 那麼,所求的元素必然不在b的前k / 2個元素中(證明反證法)反之,必然不在a的前k / 2個元素中,於是我們可以將a或b數列的前k / 2元素刪去,求剩下兩個數列的k - k / 2小元素,於是得到了資料規模變小的同類問題,遞迴解決如果 k / 2 大於某數列個數,所求元素必然不在另一數列的前k / 2個元素中,同上操作就好。

遞迴過程中的邊界條件:

1、當兩個陣列中其中有乙個為空,直接返回另外乙個的第k個元素

什麼時候會出現空,當有乙個陣列的有效比較長度恰好是k/2個,並且這個位置的元素小於另外乙個陣列的元素,該陣列的有效比較區間發生改變,這個時候會發生乙個為空乙個不為空的情況,當然也可以在初始時就進行判斷。

2、當k == 1時,返回兩個陣列起始位置的較小值

另外,在遞迴取每個陣列的第k/2大的元素時,可能陣列中a的元素已經不夠了,這個時候兩個元素的dik大必然在a和另外乙個陣列的後k/2的位置裡,此時可以將a的比較元素設定成為無窮大,保證將另外的陣列的前k/2個元素刪去。

當其中乙個陣列中的元素不夠k/2時,設其長度為l2,那麼l2 + l1(其實就是k/2) < k必然成立,那麼對於上面的陣列來說尋找的第k大就不可能在前面的l1中,必然在兩個黑色的部分中,此時將上面的陣列的前k/2個元素去除即可;

//

看做是找到兩個序列的第k大個數的問題,如果是奇數個數字那麼就是找到乙個,

//如果是偶數,那麼就找找k個和k+1個數字

class

solution

else

return

res;

}double findkth(vector& nums1, int start1, vector& nums2, int start2, int

index)

if(start2 >=nums2.size())

if(index == 1

)

int nums1_key = start1 + index / 2 - 1 >= nums1.size()? int_max : nums1[start1 + index / 2 - 1

];

int nums2_key = start2 + index / 2 - 1 >= nums2.size()? int_max : nums2[start2 + index / 2 - 1

];

if(nums1_key

else}};

find kth and find midian

此外在找到兩個陣列的第k大數字時,除了可以使用上面的額方法,還可以使用小頂堆的方式,借助堆資料結果來實現,這樣的方法是o(n)級別的,但是對於像鍊錶之類的不提供隨機讀寫的資料結構來說只能使用小頂堆的方法解決。

除了o(n)的計算方法之外還有一種比較笨重的方法就是先把這兩個目標merge到一起,然後直接去找也可以,對於多個陣列或者多個鍊錶來說就可以這麼做。

2、尋找k大元素

問題描述:在陣列中找到第k大的元素,這種可以使用快選進行查詢,總是時間複雜度是o(nlogn),與快排類似

利用快排分割的的思想,以中間位置位置元素為標桿進行劃分成左右兩部分,然後在進行判斷第k大元素在左半側還是右半側,然後進行遞迴查詢

class

solution

return kthhelper(nums, 0, nums.size() - 1

, k);

}int kthhelper(vector& nums, int start, int end, int

k)

int left =start;

int right =end;

int mid = start + (end - start)/2

;

int sign =nums[mid];

while(left <=right)

while(left <= right && nums[right]

if(left <=right)

}if(start + k - 1

<=right)

if(start + k - 1 >=left)

return nums[right + 1

]; }

};

快選

尋找有序陣列中位數

給定兩個大小為 m 和 n 的有序陣列 nums1 和 nums2。請你找出這兩個有序陣列的中位數,並且要求演算法的時間複雜度為 o log m n 你可以假設 nums1 和 nums2 不會同時為空。示例 1 nums1 1,3 nums2 2 則中位數是 2.0 示例 2 nums1 1,2 ...

LeetCode 尋找兩有序陣列中位數

給定兩個大小為 m 和 n 的有序陣列 nums1 和 nums2。請你找出這兩個有序陣列的中位數,並且要求演算法的時間複雜度為 o log m n 你可以假設 nums1 和 nums2 不會同時為空。示例 1 nums1 1,3 nums2 2 則中位數是 2.0 示例 2 nums1 1,2 ...

尋找2個有序陣列的中位數

給定兩個大小為 m 和 n 的有序陣列 nums1 和 nums2。請你找出這兩個有序陣列的中位數,並且要求演算法的時間複雜度為 o log m n 你可以假設 nums1 和 nums2 不會同時為空。示例 1 nums1 1,3 nums2 2 則中位數是 2.0 示例 2 nums1 1,2 ...