日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

leetcode 215. Kth Largest Element in an Array | 215. 数组中的第K个最大元素(Java)

發布時間:2024/2/28 java 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 leetcode 215. Kth Largest Element in an Array | 215. 数组中的第K个最大元素(Java) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目

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


題解

本題需要建立大頂堆。關于堆的數據結構,需要知道:

什么是堆?

是一棵 完全二叉樹:即使它不是滿二叉樹,也是正在從左往右變滿的過程中。

1)堆結構就是用數組實現的完全二叉樹結構

2)完全二叉樹中,如果每棵子樹的 最大值都在頂部,是 大根堆

3)完全二叉樹中,如果每棵子樹的 最小值都在頂部,是 小根堆

4)堆結構的 heapInsert 與 heapify 操作

5)堆結構的增大和減少

6)優先級隊列結構,就是堆結構

7)特點:由 N 個數 組成的堆,高度是 log(n)

如何用數組存放堆?

如果從 0 位置開始:

i 層,則

  • 左孩子:2 * i + 1
  • 右孩子:2 * i + 2
  • 父節點:(i - 1) / 2
如果從 1 位置開始:

正是由于可以使用 位運算 來代替 算數運算,效率更高,所以有時候讓下標從 1 開始。

  • 左孩子:2 * i (i << 1)
  • 右孩子:2 * i + 1 (i << 1 | 1)
  • 父節點:i / 2 (i >> 1)

如何將數組轉化成大根堆?—— heapInsert 操作

每在 i 位置加入一個新的節點,都與它的 (i - 1) / 2 位置的父節點比較,如果比父節點大,則交換(并while比較父節點與父父節點)

private void heapInsert(int[] arr, int index) {while (arr[index] > arr[(index - 1) / 2]) {swap(arr, index, (index - 1) / 2);index = (index - 1) / 2;} } private void swap(int[] arr, int i, int j) {int tmp = arr[i];arr[i] = arr[j];arr[j] = tmp; }

如何返回并刪除大根堆的最大值,剩余數字依然保持大根堆?—— heapify 操作

  • 將頂部元素取出
  • 將大根堆的最后位置上的元素覆蓋到頂部
  • while 循環
  • 如果左右孩子中較大的數比當前節點更大,則交換當前節點和較大的孩子節點
  • 如果左孩子下標越界,或左右孩子都不比當前節點大,就停止
  • // 返回最大值,并在大根堆中把最大值刪掉,剩下的數依然保持大根堆形態 public int pop() {int ans = heap[0];swap(heap, 0, --heapSize);heapify(heap, 0, heapSize);return ans; } // 從index位置開始,不斷的下沉,直到我的孩子都不再比我大,或者我已經沒孩子了,就停止 private void heapify(int[] arr, int index, int heapSize) {int left = index * 2 + 1;while (left < heapSize) {// largest存儲左右孩子 較大者 的下標int largest = left + 1 < heapSize && arr[left + 1] > arr[left] ? left + 1 : left;// largest存儲兩個孩子與父節點 較大者 的下標largest = arr[largest] > arr[index] ? largest : index;if (largest == index) { // 不需要交換的情況break;}swap(arr, largest, index);index = largest;left = index * 2 + 1;} }

    堆排序

  • 先讓整個數組都變成大根堆結構,建立堆的過程:
  • 從上到下的方法,時間復雜度為O(N*logN)
  • 從下到上的方法,時間復雜度為O(N)
  • 把堆的最大值和堆末尾的值交換,然后減少堆的大小之后,再去調整堆,一直周而復始,時間復雜度為O(N*logN)
  • 堆的大小減小成0之后,排序完成!
  • public static void heapSort(int[] arr) {if (arr == null || arr.length < 2) {return;}// 方法1:對數組進行堆排序 O(N*logN)for (int i = 0; i < arr.length; i++) { // O(N)heapInsert(arr, i); // O(logN)}// 方法2:僅將數組轉化成大頂堆 O(n) for (int i = arr.length - 1; i >= 0; i--) {heapify(arr, i, arr.length);} }

    本題代碼

    class Solution {int[] nums;int heapSize;public int findKthLargest(int[] nums, int k) {this.nums = nums;this.heapSize = nums.length;// 先讓整個數組變成大根堆結構// 方法1:從上至下 對數組進行堆排序 O(N*logN) // for (int i = 0; i < nums.length; i++) // O(N) // heapInsert(nums, i); // O(logN)// 方法2:從下至上 僅將數組轉化成大頂堆 O(N)for (int i = nums.length - 1; i >= 0; i--)heapify(nums, i, nums.length);int result = -1;for (int i = 0; i < k; i++)result = pop();return result;}public int pop() {int max = nums[0];swap(nums, 0, --heapSize);heapify(nums, 0, heapSize);return max;}// 方法1 從上至下調整堆:每在i位置加入一個新的節點,都與它的(i-1)/2位置的父節點比較,如果比父節點大,則交換(并while比較父節點與父父節點)private void heapInsert(int[] arr, int index) {while (arr[index] > arr[(index - 1) / 2]) {swap(arr, index, (index - 1) / 2);index = (index - 1) / 2;}}// 方法2 從下至上調整堆:從index位置開始,不斷的下沉,直到我的孩子都不再比我大,或者我已經沒孩子了,就停止public void heapify(int[] arr, int i, int heapSize) {int left = i * 2 + 1;while (left < heapSize) {int largest = left + 1 < heapSize && nums[left + 1] > nums[left] ? left + 1 : left; // 左右孩子較大者的下標largest = nums[largest] > nums[i] ? largest : i; // 兩個孩子與父節點較大者的下標if (largest == i) break; // 不需要交換的情況swap(arr, largest, i);i = largest; // 更新i使其下沉left = 2 * i + 1;}}private void swap(int[] arr, int i, int j) {int tmp = arr[i];arr[i] = arr[j];arr[j] = tmp;} }

    總結

    以上是生活随笔為你收集整理的leetcode 215. Kth Largest Element in an Array | 215. 数组中的第K个最大元素(Java)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。