快速选择算法

quick select 算法:

 

LintCode

5. 第k大元素

题目:在数组中找到第k大的元素

样例

给出数组 [9,3,2,4,8],第三大的元素是 4

给出数组 [1,2,3,4,5],第一大的元素是 5,第二大的元素是 4,第三大的元素是 3,以此类推

 

Solution:

class Solution {
    /*
     * @param k : description of k
     * @param nums : array of nums
     * @return: description of return
     */
    public int kthLargestElement(int k, int[] nums) {
        // write your code here
        return quickSelect(nums, 0, nums.length - 1, k);
    }

    private int quickSelect(int[] nums, int left, int right, int k) {

    //选择一个值作为支点,最后结果输出int为支点所在的位置,如果位置等于k,输出,否则继续自身调用
        int pivot = nums[left];
        int i = left, j = right;
        while (i <= j) {
            //寻找左侧小于支点的元素
            while (i <= j && nums[i] > pivot) {
                i++;
            }
            //寻找右侧大于支点的元素
            while (i <= j && nums[j] < pivot) {
                j--;
            }
            //将选择出来的i或j与支点互换(此时支点为i或j,即前两个while中其中一个等于支点直接跳出)
            if (i <= j) {
                int tmp = nums[i];
                nums[i] = nums[j];
                nums[j] = tmp;
                i++;
                j--;
                //对应下方left~j,i~right
            }
        }

        //判断k的位置在支点的左或右,选择一部分执行
        if (left + k - 1 <= j) {
            return quickSelect(nums, left, j, k);
        }
        if (left + k - 1 >= i) {
            return quickSelect(nums, i, right, k - (i - left));
        }
        return nums[j + 1];
    }
}

(代码源自九章算法,注释自笔者)

快速选择算法与快速排序算法的区别在于,快速选择算法只会对支点的一侧进行排序,或者输出。

这种算法是不能有重复值的,因为每次都要与pivot交换,遇到与pivot相等的值会陷入死循环交换,故而这种方式不能用于快速排序。

快速排序:

public class QuickSortSolution {
    public void sortArr(int[] source) {
        sort(source,0,source.length-1);
    }

    private void sort(int[] nums, int left, int right) {
        if(left>=right)
            return;

        int i = left;//后面先+1,这个做pivot
        int j = right + 1;//因为后面要先+1
        //两个位置都超出范围1个位置

        int pivot = nums[left];

        while (true) {
            while(i+1<nums.length&&nums[++i]<pivot);
            while(j>=0&&nums[--j]>pivot);

            if(i>=j)
                break;
            else {
                int temp = nums[i];
                nums[i] = nums[j];
                nums[j] = temp;
            }

        }
        nums[left] = nums[j];
        nums[j] = pivot;
        //将j+1=i j寻找到比pivot小的置换为pivot
        //j指向pivot

        sort(nums,left,j-1);
        sort(nums,j+1,right);
    }

}

 

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值