zoukankan      html  css  js  c++  java
  • 215. Kth Largest Element in an Array

    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.

    Example 1:

    Input: [3,2,1,5,6,4] and k = 2
    Output: 5
    

    Example 2:

    Input: [3,2,3,1,2,4,5,5,6] and k = 4
    Output: 4

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

    M1: 用min heap

    维护一个大小为k的min heap

    time: O(k + (n-k)logk), space: O(k)

    class Solution {
        public int findKthLargest(int[] nums, int k) {
            PriorityQueue<Integer> minHeap = new PriorityQueue<>();
            for(int n : nums) {
                minHeap.offer(n);
                if(minHeap.size() > k)
                    minHeap.poll();
            }
            return minHeap.peek();
        }
    }

    M2: max heap

    把所有元素入队,再一个个poll出来

    time: O(n + klogn), space: O(n)

    class Solution {
        public int findKthLargest(int[] nums, int k) {
            PriorityQueue<Integer> maxHeap = new PriorityQueue<>((a, b) -> b - a);
            for(int n : nums) {
                maxHeap.offer(n);
            }
            int res = 0;
            while(maxHeap.size() > nums.length - k) {
                res = maxHeap.poll();
            }
            return res;
        }    
    }

    M3: sort

    基于select sort

    time: O(nlogn), space: O(logn)

    class Solution {
        public int findKthLargest(int[] nums, int k) {
            Arrays.sort(nums);
            return nums[nums.length - k];
        }
    }

    M4: quick select

    和selection sort思路一样,选择一个元素作为基准来对元素进行分区,将小于和大于基准的元素分在基准左边和右边的两个区域。不同的是,快速选择并不递归访问双边,而是只递归进入一边的元素中继续寻找。这降低了平均时间复杂度,从O(n log n)至O(n),不过最坏情况仍然是O(n2)。  -- from wikipedia

    https://stackoverflow.com/questions/5945193/average-runtime-of-quickselect/25796762#25796762

    每次选区间的最右值作为pivot,然后把小于pivot的值放在左边,大于等于pivot的值放在右边

    每次舍去不符合条件的一半,n+(n/2)+(n/4)..1 = n + (n-1) = O(2n-1) = O(n)

    time: O(n)  -- worst case O(n ^ 2),  space: O(1)

    class Solution {
        public int findKthLargest(int[] nums, int k) {
            return quickSelect(nums, 0, nums.length - 1, nums.length - k);
        }
        
        private int quickSelect(int[] nums, int left, int right, int target) {
            if (left > right) {
                return Integer.MAX_VALUE;
            }
            int pivot = nums[right];
            int start = left, end = right - 1;
            while(start <= end) {
                if(nums[start] < pivot) {
                    start++;
                } else if(nums[end] >= pivot) {
                    end--;
                } else {
                    swap(nums, start++, end--);
                }
            }
            swap(nums, start, right);
                    
            if(start == target) {
                return nums[start];
            } else if(start < target) {
                return quickSelect(nums, start + 1, right, target);
            } else {
                return quickSelect(nums, left, start - 1, target);
            }
        }
        
        private void swap(int[] nums, int i, int j) {
            int tmp = nums[i];
            nums[i] = nums[j];
            nums[j] = tmp;
        }
    }

    二刷:

    class Solution {
        public int findKthLargest(int[] nums, int k) {
            return quickSelect(nums, 0, nums.length - 1, nums.length - k);
        }
        
        public int quickSelect(int[] nums, int left, int right, int target) {
            if(left > right) {
                return Integer.MAX_VALUE;
            }
            Random r = new Random();
            int pivotIdx = left + r.nextInt(right - left + 1);
            int pivot = nums[pivotIdx];
            swap(nums, pivotIdx, right);
            int start = left, end = right - 1;
            while(start <= end) {
                if(nums[start] < pivot) {
                    start++;
                } else if(nums[end] >= pivot) {
                    end--;
                } else {
                    swap(nums, start++, end--);
                }
            }
            swap(nums, start, right);
            
            if(start == target) {
                return nums[start];
            } else if(start < target) {
                return quickSelect(nums, start + 1, right, target);
            } else {
                return quickSelect(nums, left, start - 1, target);
            }
        }
        
        public void swap(int[] arr, int i, int j) {
            int tmp = arr[i];
            arr[i] = arr[j];
            arr[j] = tmp;
        }
    }
  • 相关阅读:
    一百零二、SAP中ALV事件之十五,让ALV表格自动求和
    一百零一、SAP中ALV事件之十四,让ALV表格自动排序
    一百、SAP中ALV事件之十三,给ALV的自定义按钮添加事件
    九十九、SAP中ALV事件之十二,给ALV的标题栏添加图片
    九十八、SAP中ALV事件之十一,查看图片
    九十七、SAP中ALV事件之十,通过REUSE_ALV_COMMENTARY_WRITE函数来显示ALV的标题
    九十六、SAP中ALV事件之九,显示功能按钮栏中显示ALV加强工具栏
    九十五、SAP中查看自定义包的所有模块,对象,函数主,事务等
    二十、JavaScript之对象
    十九、JavaScript之数组
  • 原文地址:https://www.cnblogs.com/fatttcat/p/9988187.html
Copyright © 2011-2022 走看看