[LeetCode] 215.配列内のK番目に大きい要素(C ++)


件名のソース:https//leetcode-cn.com/problems/kth-largest-element-in-an-array/

タイトル説明

ソートされていない配列で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番目に大きい要素を探します。要素の重複の問題を考慮する必要はありません

並べ替え後に添え字を削除する

  • コードの量が最も少ない最も大雑把な方法は、並べ替え後に添え字-1を返すことです。この方法の平均時間計算量はO(nlogn)で、平均空間計算量はO(logn)です。配列を盲目的に並べ替えますが、それは必要ない。
class Solution {
    
    
public:
    int findKthLargest(vector<int>& nums, int k) {
    
    
        int len = nums.size();
        if(len == 1)    return nums[0];
        sort(nums.begin(), nums.end(), greater<int>() );
        return nums[k - 1];
    }
};

複雑さの分析

  • 時間計算量:O(nlogn)。nは配列の長さ、aはn回トラバースされ、bとcのトラバーサルの時間計算量はO(n)です。
  • スペースの複雑さ:O(logn)。nは配列の長さであり、クイックソートで使用される平均スペース複雑度はO(logn)です。最悪の場合、n-1回の再帰呼び出しが必要であり、スペース複雑度はO(n)です。

高速ソートのアイデアO(n)を使用して、K番目に大きい要素を見つけます

  • 並べ替え後、配列は番兵によって2つの等しい部分に分割されていることがわかります(配列が大きいものから小さいものに並べ替えられていると仮定します)。左側のすべての要素は歩哨よりも大きく、上のすべての要素は右は番兵よりも小さいです。番兵の添え字がpであるとすると、この時点で番兵は配列(p + 1)の最大要素です。p+ 1 = Kの場合、A [p]は次の要素になります。解決済み; K> p + 1、K番目に大きい要素の場合要素はA [p + 1…n-1]の間隔で表示され、次にA [p + 1…n-1]の間隔で再帰的に検索します同様に、K <p + 1の場合、A [0 ... p-1]の間隔で検索します。
  • 次のコードも最適化できます(3つの数値の中から最適化されたセンチネルを選択します)が、
    A [0…p− 1] A [p] A [p + 1…n− 1] A [0…p-1 ] {\ qquad} A [p] {\ qquad} A [p + 1…n-1]A [ 0p1 ]A [ p ]A [ p+1n1 ]
class Solution {
    
    
public:
    int findKthLargest(vector<int>& nums, int k) {
    
    
        int len = nums.size();
        if(len == 1)	return nums[0];
        int ans = finK(nums, 0, len-1, k);
        return ans;
    }
    int finK(vector<int>& nums, int start, int end, int k){
    
    
        int left = start, right = end;
        int key = nums[start];
        while(left < right){
    
    
            while(nums[right] <= key && left < right)   --right;
            nums[left] = nums[right];
            while(nums[left] >= key && left < right)    ++left;
            nums[right] = nums[left];
        }
        nums[left] = key;
        if(left + 1 == k)	return nums[left];
        else if(left + 1 > k )	return finK(nums, start, left - 1, k);
        else	return finK(nums, left + 1, end, k);
    }
};

複雑さの分析

  • 時間計算量:O(n)。nは配列の長さです。サイズnの配列でパーティション操作を実行するには、n個の要素をトラバースする必要があります。2番目のパーティション検索はn / 2回トラバースする必要があり、間隔が1に減少し、トラバースされた要素の数の合計が2 * n-1(等比数列の合計式)になるまで続きます。
  • スペースの複雑さ:O(logn)。nは配列の長さであり、クイックソートで使用される平均スペース複雑度はO(logn)です。最悪の場合、n-1回の再帰呼び出しが必要であり、スペース複雑度はO(n)です。

おすすめ

転載: blog.csdn.net/lr_shadow/article/details/114022764