Idiot-maker

  :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

https://leetcode.com/problems/kth-largest-element-in-an-array/description/

Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element.

For example,
Given [3,2,1,5,6,4] and k = 2, return 5.

Note: 
You may assume k is always valid, 1 ≤ k ≤ array's length.

解题思路:

这题是比较古老的排序题目了,经典的表述是求数组中第k大或者第k小的数字。这种题,用一个O(nlogn)的比较排序,然后直接取第k个 第(前)k大数问题 的总结。

我以前也转载过相关解法 求已知N个数中第k小的数

这道题的解法是比较综合的。首先,递归分治,借鉴了快速排序的思路,将数组根据任意元素(这里取第一个)分成两半,a.如果从end到pivot正好k个,那么就是第pivot个元素。b.如果end到pivot>k个,递归处理pivot+1到end,取第k个。c.如果小于k个,则取前半段(start到pivot-1),取第k-(end - pivot+1)个。

其次,根据上面的表述,和binary search也很像吧。一不小心就会出现stack overflow的问题,开始我就写错了,注释掉了。因为在pivot==start的时候,start得不到更新,死循环了。

时间复杂度,因为上面的b和c每次只选择执行一次,而不是像快排,每次两个都要执行。所以时间复杂度为O(n)。

因为O(n+n/2+n/4...) = O(2n)。

public class Solution {
    public int findKthLargest(int[] nums, int k) {
        return find(nums, 0, nums.length - 1, k);
    }
    
    public int find(int[] nums, int start, int end, int k) {
        if(start > end) {
            return -1;
        }
        int pivot = partition(nums, start, end);
        if(end - pivot + 1 == k) {
            return nums[pivot];
        } else if(end - pivot + 1 > k) {
            // return find(nums, pivot, end, k);
            return find(nums, pivot + 1, end, k);
        } else {
            return find(nums, start, pivot - 1, k - (end - pivot + 1));
        }
    }
    
    public int partition(int[] nums, int start, int end) {
        if(start == end) {
            return start;
        }
        int pivot = start + 1;
        for(int i = start + 1; i <= end; i++) {
            if(nums[i] < nums[start]) {
                int temp = nums[pivot];
                nums[pivot] = nums[i];
                nums[i] = temp;
                pivot++;
            }
        }
        int temp = nums[pivot - 1];
        nums[pivot - 1] = nums[start];
        nums[start] = temp;
        return pivot - 1;
    }
}

 // 20181015

这里的partition用快排中的partition2更清晰

https://www.cnblogs.com/NickyYe/p/4645410.html

class Solution {
    public int findKthLargest(int[] nums, int k) {
        return find(nums, k, 0, nums.length - 1);
    }
    
    public int find(int[] nums, int k, int start, int end) {
        int pivot = partition(nums, start, end);
        if (k == end - pivot + 1) {
            return nums[pivot];
        } else if (k < end - pivot + 1) {
            return find(nums, k, pivot + 1, end);
        } else {
            return find(nums, k - (end- pivot) - 1, start, pivot - 1);
        }
    }
    
    public int partition(int[] nums, int start, int end) {
        int pivot = nums[start], i = start, j = end;
        while (i < j) {
            while (i <= end && nums[i] <= pivot) {
                i++;
            }
            while (nums[j] > pivot) {
                j--;
            }
            if (i > j) {
                break;
            }
            int temp = nums[i];
            nums[i] = nums[j];
            nums[j] = temp;
        }
        // j不可能<start,因为nums[start] == pivot
        int temp = nums[start];
        nums[start] = nums[j];
        nums[j] = temp;
        return j;
    }
}

 

posted on 2015-06-05 21:35  NickyYe  阅读(163)  评论(0编辑  收藏  举报