Likouブラッシング質問百日計画Day14配列内でK番目に大きい要素Likou質問バンクNo.215C#ダブルポインター中難易度

学習目標:

私はあなたに異なる思考の拡張をもたらすことを望んで、私のユニークなアルゴリズムのアイデアを更新し続けます!
役に立ったら、いいね、フォロー、サポートしてください!
あなたの励ましは私を動かし続けるものです!

歴口質問銀行質問215公式リンク

学習コンテンツ:

配列内でK番目に大きい要素

给定整数数组 nums 和整数 k,请返回数组中第 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

提示:

1 <= k <= nums.length <= 104
-104 <= nums[i] <= 104

ソース:LeetCode
リンク:https ://leetcode-cn.com/problems/kth-largest-element-in-an-array

勉強の時間:

2022.1.27


学習出力:

アイデア1

クイックソートここに画像の説明を挿入

問題解決のアイデア
クイックソートを使用して配列をソートし、最大数に従って対応する配列位置の値を取得します

  1. まず、クイックソートアルゴリズムのアイデアを思い出してみましょう。最初に、左右に2つのポインターがあり、次にベースアドレスが0アドレスを指します。次に、左のポインタが右に移動し、右のポインタが左に移動します。1つ目は、右ポインタを左に移動することです。右ポインタの値がベースアドレスの値よりも小さい場合は、左ポインタを移動します。左ポインタが右に移動します。この時点で左ポインタの値がベースアドレスの値よりも大きい場合は、左ポインタと右ポインタが指す値が交換されます。2つのポインターが出会うまで、ソートが完了します.2つのポインターが出会う場所が新しいベースアドレスであり、ベースアドレスは新しいベースアドレスを指します。
  2. 1回の操作が完了すると、ベースアドレスの左側がベースアドレスよりも小さい値になり、右側がベースアドレスよりも大きい値になります。
  3. 次に、ベースアドレスの左側を新しい配列として並べ替えます。ベースアドレスの右側にあるものは、新しい配列としてソートされます。次に、123のプロセスを繰り返すと、並べ替えられた配列を取得できます
  4. 次に、必要なk番目に大きい値に対応する配列内の位置を返します
public class Solution {
    
    
    public int FindKthLargest(int[] nums, int k) {
    
    
        QuickSort(nums,0,nums.Length-1);//快速排序
        return nums[nums.Length-k];
    }

    void QuickSort(int[] nums, int begin, int end)
    {
    
    
        if(begin>=end)return; //如果长度为1 或者小于1 那就没有快速排序的必要
        int temp=nums[begin];  //暂存begin位置的值
        int index=begin;  //暂存begin的值
        int left=begin;  //左边的值  左指针
        int right=end;   //右边的值   右指针
        while(begin<end){
    
            //一直循环到左边指针和右边指针相遇
            if(nums[end]>=temp&& begin < end){
    
          //右指针找到一个比begin指针小的值
                end--;
                continue;
            }
            if(nums[begin]<=temp&& begin < end){
    
        //左指针找到一个比begin指针大的值
                begin++;
                continue;
            }
            //到这里 左指针已经找到比begin指针大的值  右指针也找到比begin指针小的值
            //所以 交换左右指针的值 达到目的 
            //让比begin指针大的值全去右边 比begin指针小的值全去左边
            int cur=nums[end];
            nums[end]=nums[begin];
            nums[begin]=cur;
        }
		
		//while循环完 则左右指针相遇
		//则把begin暂存的值和现在左右指针的位置的值进行交换即可
        nums[index]=nums[end];
        nums[end]=temp;
		
		//现在end位置就是中间点,小于end,就是比end指向的值小。 大于end就是比end指向的值大
        QuickSort(nums,left,end-1);  //继续排end左边的数组
        QuickSort(nums,begin+1,right);   //继续排end右边的数组

    }
}

アイデア2

クイックソートの最適化ここに画像の説明を挿入

問題解決のアイデア

  1. まず、クイックソートアルゴリズムのアイデアを思い出してみましょう。最初に、左右に2つのポインターがあり、次にベースアドレスが0アドレスを指します。次に、左のポインタが右に移動し、右のポインタが左に移動します。1つ目は、右ポインタを左に移動することです。右ポインタの値がベースアドレスの値よりも小さい場合は、左ポインタを移動します。左ポインタが右に移動します。この時点で左ポインタの値がベースアドレスの値よりも大きい場合は、左ポインタと右ポインタが指す値が交換されます。2つのポインターが出会うまで、ソートが完了します.2つのポインターが出会う場所が新しいベースアドレスであり、ベースアドレスは新しいベースアドレスを指します。
  2. 1回の操作が完了すると、ベースアドレスの左側がベースアドレスよりも小さい値になり、右側がベースアドレスよりも大きい値になります。
  3. では、配列全体を並べ替えてから、対応する最大値を取り出す必要がありますか?
  4. 必要はありません。ベースアドレスが対応するサイズのインデックス値である必要があります。たとえば、2番目に大きい値が必要です。次に、1回の操作の後、取得した新しいベースアドレスは、必要な最大の位置になります。次に、この位置の左側はそれよりも小さく、右側はそれよりも大きくなります。その後、残りを並べ替える必要はありません。このベースアドレスが私たちが探しているものだからです
  5. 1で並べ替えて取得した新しいベースアドレスが必要なインデックスよりも小さい場合は、右側を並べ替えるだけです。結果の新しいベースアドレスが必要なインデックスよりも大きい場合は、左側を並べ替えるだけです。次に、残りを並べ替えてから、新しいベースアドレスを取得し、判断を続けます。
  6. このようにして、多くの不要な計算を節約できます
public class Solution {
    
    
    public int FindKthLargest(int[] nums, int k) {
    
    
        k = nums.Length - k;  //找到我们想要的第k大的数据应该在排序完数组的位置
        int l = 0, h = nums.Length - 1;
        while (l < h) {
    
    
            //找到现在排序完的中点位置
            int j = QuickSort(nums, l, h);
            
            if (j == k) {
    
                //如果中点就是我们想要的位置就对了
                break;
            } else if (j < k) {
    
         //如果中点比目标位置小,那就只需要将中点右边的继续排就行了
                l = j + 1; 
            } else {
    
                //如果中点比目标位置大,那就只需要将中点左边的继续排就行了
                h = j - 1;
            }
        }
        return nums[k];
    }


    int QuickSort(int[] nums, int begin, int end)
    {
    
    
        if(begin>=end)return end; //如果长度为1 或者小于1 那就没有快速排序的必要
        int temp=nums[begin];  //暂存begin位置的值
        int index=begin;  //暂存begin的值
        int left=begin;  //左边的值  左指针
        int right=end;   //右边的值   右指针
        while(begin<end){
    
            //一直循环到左边指针和右边指针相遇
            if(nums[end]>=temp&& begin < end){
    
          //右指针找到一个比begin指针小的值
                end--;
                continue;
            }
            if(nums[begin]<=temp&& begin < end){
    
        //左指针找到一个比begin指针大的值
                begin++;
                continue;
            }
            //到这里 左指针已经找到比begin指针大的值  右指针也找到比begin指针小的值
            //所以 交换左右指针的值 达到目的 
            //让比begin指针大的值全去右边 比begin指针小的值全去左边
            int cur=nums[end];
            nums[end]=nums[begin];
            nums[begin]=cur;
        }
		
		//while循环完 则左右指针相遇
		//则把begin暂存的值和现在左右指针的位置的值进行交换即可
        nums[index]=nums[end];
        nums[end]=temp;
		
        return end;


    }
}

アイデア3

ヒープソート

著者:モルモットXiaohuihui
著作権は著者に帰属します。商用の再版については、著者に連絡して許可を求め、非商用の再版については、出典を示してください。

おすすめ

転載: blog.csdn.net/m0_48781656/article/details/122745398