day16

第一题

        

        

题意:将一个数组按照0,1,2的顺序依次从左到右排序并输出;

        本题我们引入三指针的解题思路:

        如下所示:

定义三个指针left指针,right指针,i指针,将整个数组分为一下区域:

【0,left】:全是为0的区域;

【left+1,i-1】:全是为1的区域;

【i,right-1】:里面的数字全是为违背扫描的区域;

【right,n-1】:全是为0的区域;

        对于指针移动的细节如下所示:

        当当前的i指针所指的数字为0时,左指针右移一位之后所指的数字和当前i指针所指的数字相交换,之后i指针向右移动一位;

        当前的i指针所指的数字为1时,i指针向右移动一位既可;

        当前的i指针所指的数字为1时,右指针左移一位之后所指的数字和当前i指针所指的数字相交换,之后i指针不变不用移动;

综上所述,代码如下:

class Solution {
    public void swap(int[] nums, int i, int j)
    {
        int t = nums[i];
        nums[i] = nums[j];
        nums[j] = t;
 
    }
    public void sortColors(int[] nums) {
        int left = -1,right = nums.length,i = 0;
        while (i < right){
            if(nums[i] == 0){
                swap(nums,++left,i++);
            }else if(nums[i] == 1){
                i++;
            }else{
                swap(nums,--right,i);
            }
        }
    }
}

 第二题

        

本题采用快速排序的思想:

        在一个数组中找到一个key,将整个数组分为两个区域,左区域的所有书<=key,有区域的所有书都>key;并且下一步在上面左区域中用林外一个key1,将上述左区域分为只能得左区域1和有区域2,;同时将上述有区域也使用key2划分为左区域2,右区域2,这样一直划分下去;

        故此我们使用“数组分三块”的思想来使用快速排序:总体思路如上题故事:

        在选择基准元素的过程中,我们为了优化选择,采用随机的方式选择基准元素;

        

class Solution {
    public int[] sortArray(int[] nums) {
        qsort(nums,0,nums.length - 1);
        return nums;
    }

    public void qsort(int[] nums,int l,int r){
        if(l >= r){
            return;
        }
        //使用随机的方式来选择基准元素
        int key= nums[new Random().nextInt(r-l+1)+l];
        int left = l -1,right = r +1,i=l;
        while(i < right){
            if(nums[i] < key) {
                swap(nums,++left,i++);
            }else if(nums[i] == key){
                i++;
            }else{
                swap(nums,--right ,i);
            }
        }
        qsort(nums,l,left);
        qsort(nums,right,r);
    }

    public void swap(int[] nums,int i,int j){
        int t = nums[i];
        nums[i] = nums[j];
        nums[j] = t;
    }
}

 第三题

        我们本题苦采用快速排序法和三指针将数组分三块以及随机选择基准的方法来解决:

        上图所示,我们的区域分为三块,我们要选择的第k大的数字,所以分析如下:假设我们左区域的长度为a,中间区域的长度为b,右边区域的长度为c;

        进行判断,

        当右边区域的长度大于k时,k的值在右边区域我们要去右边的区域进行进一步划分区域查找;

        当中间和右边的区域长度大于k值时,我们索取的k就在中间区域;,此时直接返回中间区域的值;

        当上述的情况都不满足是,我们的k就在左边区域,所以我们要在左边的区域里面进行划分区域和进一步查找;但是我们应该查找的是第k-b-c的小值;

        故此,代码如下:

class Solution {
    public int findKthLargest(int[] nums, int k) {
        return qsort( nums,0,nums.length-1,k);
    }

    public void swap(int[] nums, int left, int right) {
        int t = nums[left];
        nums[left] = nums[right];
        nums[right] = t;
    }

    public int qsort(int[] nums,int l,int r,int k){
        if(l == r) return nums[l];

        int key = nums[new Random().nextInt(r - l +1)+l];
        int left = l-1,right = r+1,i = l;
        while(i < right){
            if(nums[i] < key){
                swap(nums,++left,i++);
            }else if (nums[i] == key){
                i++;
            }else{
                swap(nums,--right ,i);
            }
        }
        //【l,left】【left+1,right -1】【right,r】
        int b = right -left -1,c =r- right +1;
        if(c >=k) return qsort(nums,right,r,k);
        else if (b+c >= k) return key;
        else return qsort(nums,l,left,k-b-c);

    }
}

ps:本次的内容就到这里了,如果大家感兴趣的话就请一键三连哦!!! 

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值