陣列中第k大的元素

2021-10-06 20:45:25 字數 1986 閱讀 2402

問題描述:

在未排序的陣列中找到第 k 個最大的元素。請注意,你需要找的是陣列排序後的第 k 個最大的元素,而不是第 k 個不同的元素。

示例 1:

輸入: [3,2,1,5,6,4] 和 k = 2

輸出: 5

示例 2:

輸入: [3,2,3,1,2,4,5,5,6] 和 k = 4

輸出: 4

說明:你可以假設 k 總是有效的,且 1 ≤ k ≤ 陣列的長度。

解法一:使用最大堆

將陣列構建成乙個最大堆,然後依次從裡往外彈元素,彈到第k個即為所求,實現**如下:

class solution 

public void adjust(int i)

int cur = data[i];

while(2 * i + 1 < length)

if(cur >= data[max])

data[i] = data[max];

i = max;

}data[i] = cur;

}public int poll()

int result = data[0];

data[0] = data[--length];

adjust(0);

return result;}}

public int findkthlargest(int nums, int k)

int result = 0;

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

return result;

}}

解法二:解法一的優化(使用最小堆)

使用陣列中前k個元素建立乙個大小為k的最小堆,遍歷剩下的元素,若當前元素大於等於堆頂元素,則說明當前元素一定不處於最大的k個元素之中,若小於堆頂元素,則彈出堆頂元素,插入當前結點。最終該堆中的元素就為最大的k個元素。堆頂元素即為第k大的元素,時間複雜度由原來的o(nlogn)降為o(nlog(k))實現**如下:

class solution 

public void init(int nums)

for(int i = data.length - 1; i >= 0; i--)

}public void adjust(int i)

int cur = data[i];

while(2 * i + 1 < data.length)

if(cur <= data[min])

data[i] = data[min];

i = min;

}data[i] = cur;

}public void add(int val)

data[0] = val;

adjust(0);}}

public int findkthlargest(int nums, int k)

return minheap.data[0];

}}

解法三:使用快排的思想

從陣列中任意挑選乙個值,將陣列分隔為大於該值的在前面,等於該值的在中間,小於該值的在後邊。不妨設這三個區間為[left, i) [i, j], (j , right],若 k - 1 落入第乙個區間,對第乙個區間進行上述操作,落入第二個區間則證明找到了,返回即可,落入第三個區間則對第三個區間進行上述操作。實現**如下:

public int findkthlargest(int nums, int k) else if(nums[n] == mid)else

}if(k - 1 > j)else if(k - 1 < i)else

}if(nums[left] < nums[right])

return nums[k - 1];

}public void sweap(int nums, int i, int j)

假設每次隨機找到的值近似於中位數,則其時間複雜度為o((logn)^2),由於外迴圈是乙個二分,內迴圈亦是乙個二分。

尋找陣列中的第K大的元素

遇到了乙個很簡單而有意思的問題,可以看出不同的演算法策略對這個問題求解的優化過程。問題 尋找陣列中的第k大的元素。最簡單的想法是直接進行排序,演算法複雜度是o n logn 這麼做很明顯比較低效率,因為不要求別的資訊只要計算出第k大的元素。當然,如果在某種情況下需要頻繁訪問第k大的元素就可以先進行一...

輸出陣列第k大的元素

用快速排序的思想輸出陣列第k大的元素 1 include2 include3 using namespace std 45 遞迴實現 返回陣列第k大的值.陣列下標區間是 begin,end 其中陣列假定n個元素,則k的值在區間 1,n 6 能夠使用這種方法的前提條件是 n個數不能重複。如果n個數中有...

最壞情況O N 求陣列中第K 大的元素。

求陣列中第k的元素的一般方法就是使用快速排序的劃分,partion seq,start,end p,如果p k 則ok。如果p k 則在start,p 1的區間裡找第k大的數,partion seq,start,p 1 否則partion seq,p 1,end 演算法的平均時間複雜度為o n 最壞...