力扣刷题百天计划 Day14 数组中的第K个最大元素 力扣题库第215题 C# 双指针 中等难度

学习目标:

我会持续更新我独特的算法思路,希望能给大家带来不一样的思维拓展!
如果大家感觉有帮助的话,欢迎点赞关注支持哦!
你们的鼓励是我坚持下去的动力!
!!!

力扣题库第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. 首先我们回忆一下快速排序算法的思路,首先是两个指针在左边和右边,然后一个基地址指向0地址。然后左指针右移,右指针左移。首先是右指针左移,如果右指针的值小于基地址的值,那么就去移左指针。左指针右移,如果此时左指针的值大于基地址的值,那么现在开始交换左右指针指向的值。直到两个指针相遇,则完成一次排序,两个指针相遇的地方,就是新的基地址,将基地址指向现在这个新的基地址
  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右边的数组

    }
}

思路二

快速排序优化在这里插入图片描述

解题思路

  1. 首先我们回忆一下快速排序算法的思路,首先是两个指针在左边和右边,然后一个基地址指向0地址。然后左指针右移,右指针左移。首先是右指针左移,如果右指针的值小于基地址的值,那么就去移左指针。左指针右移,如果此时左指针的值大于基地址的值,那么现在开始交换左右指针指向的值。直到两个指针相遇,则完成一次排序,两个指针相遇的地方,就是新的基地址,将基地址指向现在这个新的基地址
  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;


    }
}

思路三

堆排序

作者:荷兰猪小灰灰
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

猜你喜欢

转载自blog.csdn.net/m0_48781656/article/details/122745398