堆排序 && Kth Largest Element in an Array
堆排序
堆节点的访问
通常堆是通过一维数组来实现的。在数组起始位置为0的情形中:
父节点i的左子节点在位置(2*i+1);
父节点i的右子节点在位置(2*i+2);
子节点i的父节点在位置floor((i-1)/2);
堆的操作
在堆的数据结构中,堆中的最大值总是位于根节点(在优先队列中使用堆的话堆中的最小值位于根节点)。堆中定义以下几种操作:
最大堆调整(Max_Heapify):将堆的末端子节点作调整,使得子节点永远小于父节点
创建最大堆(Build_Max_Heap):将堆所有数据重新排序。从最后一个父节点开始调用“最大堆调整”,直到第一个父节点(根节点)
堆排序(HeapSort):移除位在第一个数据的根节点,并做最大堆调整的递归运算
Java
1 package test; 2 3 public class Solution { 4 5 private void maxHeapify(int[] nums, int index, int heapSize) { 6 int iMax, iLeft, iRight; 7 while(true) { 8 iMax = index; 9 iLeft = 2 * index + 1; 10 iRight = 2 * index + 2; 11 12 if (iLeft < heapSize && nums[iMax] < nums[iLeft]) { 13 iMax = iLeft; 14 } 15 if (iRight < heapSize && nums[iMax] < nums[iRight]) { 16 iMax = iRight; 17 } 18 19 if(iMax != index) { 20 int tmp = nums[iMax]; 21 nums[iMax] = nums[index]; 22 nums[index] = tmp; 23 index = iMax; 24 } else { 25 break; 26 } 27 } 28 } 29 30 private void buildMaxHeap(int[] nums) { 31 int lastParent = (int) Math.floor((nums.length-1) / 2); 32 for(int i=lastParent; i>=0; i--) { 33 maxHeapify(nums, i, nums.length); 34 } 35 } 36 37 public void heapSort(int[] nums) { 38 buildMaxHeap(nums); 39 40 for(int i=nums.length-1; i>=0; i--) { 41 int tmp = nums[0]; 42 nums[0] = nums[i]; 43 nums[i] = tmp; 44 maxHeapify(nums, 0, i); 45 } 46 } 47 48 public static void main(String[] args) { 49 // TODO Auto-generated method stub 50 int[] nums = {3,5,2,1,0,9,4,5,6,7,3,2,6}; 51 Solution s = new Solution(); 52 s.heapSort(nums); 53 for(int num: nums) { 54 System.out.print(num + " "); 55 } 56 } 57 58 }
参考
https://zh.wikipedia.org/wiki/堆排序
http://bubkoo.com/2014/01/14/sort-algorithm/heap-sort/
Kth Largest Element in an Array
来源:https://leetcode.com/problems/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.
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大的元素。
也可利用快速排序的思想,见http://www.cnblogs.com/renzongxian/p/7465453.html
Java
1 class Solution { 2 private void maxHeapify(int[] nums, int index, int heapSize) { 3 int iMax, iLeft, iRight; 4 while(true) { 5 iMax = index; 6 iLeft = 2 * index + 1; 7 iRight = 2 * index + 2; 8 if(iLeft < heapSize && nums[iMax] < nums[iLeft]) { 9 iMax = iLeft; 10 } 11 if(iRight < heapSize && nums[iMax] < nums[iRight]) { 12 iMax = iRight; 13 } 14 15 if(iMax != index) { 16 int tmp = nums[iMax]; 17 nums[iMax] = nums[index]; 18 nums[index] = tmp; 19 index = iMax; 20 } else { 21 break; 22 } 23 } 24 } 25 26 private void buildMaxHeap(int[] nums) { 27 int lastParent = (int)Math.floor((nums.length-1) / 2); 28 for(int i=lastParent; i>=0; i--) { 29 maxHeapify(nums, i, nums.length); 30 } 31 } 32 33 public int findKthLargest(int[] nums, int k) { 34 buildMaxHeap(nums); 35 for(int i=nums.length-1; i>=nums.length-k; i--) { 36 int tmp = nums[0]; 37 nums[0] = nums[i]; 38 nums[i] = tmp; 39 maxHeapify(nums, 0, i); 40 } 41 return nums[nums.length-k]; 42 } 43 } // 7 ms