欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java實(shí)現(xiàn)TopK問題的方法

 更新時間:2019年08月14日 09:27:38   作者:早就戒了  
這篇文章主要介紹了Java實(shí)現(xiàn)TopK問題的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

面試中會經(jīng)常遇到手撕代碼的情況,而求TopK的是經(jīng)常遇到的題目。下面我就用Java來實(shí)現(xiàn)。主要通過兩種方法實(shí)現(xiàn),快排思想以及堆排序的思想,兩者的復(fù)雜度為O(NlogK)。

基于快排的TopK實(shí)現(xiàn):

import java.util.Arrays;

/**
 * 使用快排實(shí)現(xiàn)的TopK問題 Title: Description: Company:
 * 
 * @author 鄭偉
 * @date 2018年4月10日下午9:28:15
 */
public class TopK_PartitionSort {

  public static void main(String[] args) {

    int[] num = { 2, 20, 3, 7, 9, 1, 17, 18, 0, 4 };
    partitionSort(num, 0, num.length - 1, 3);
    System.out.println(Arrays.toString(num));
  }

  public static void partitionSort(int[] nums, int low, int high, int K) {
    if (low < high) {
      int pointKey = partitionSortCore(nums, low, high);
      if (K - 1 == pointKey)//TopK問題的核心,就是如果返回的下標(biāo)為K-1,說明已經(jīng)排序好了K個最大/最小的數(shù),但是之間的順序是不確定的
        return;
      partitionSort(nums, low, pointKey - 1, K);
      partitionSort(nums, pointKey + 1, high, K);
    }
  }

  /**
   * 快排的核心
   * 
   * @param nums
   * @param low
   * @param high
   * @return 返回排序好以后的位置
   */
  public static int partitionSortCore(int[] nums, int low, int high) {
    // 以第一個座位標(biāo)志位來比對
    int pivotkey = nums[low];
    while (low < high) {
      // 從pivotkey往最后一個位置比較
      while (low < high && pivotkey <= nums[high]) {
        --high;
      }
      // 開始交換pivotkey和nums[high]
      int temp = nums[low];
      nums[low] = nums[high];
      nums[high] = temp;
      // 此時nums[high]對應(yīng)于pivotkey
      while (low < high && pivotkey >= nums[low]) {
        ++low;
      }
      // 找到比pivotkey大的書了,那就交換
      temp = nums[low];
      nums[low] = nums[high];
      nums[high] = temp;
      // 這時,pivotkey對應(yīng)于nums[low]
    }
    return low;// 返回pivotkey對應(yīng)的正確位置
  }

}

其實(shí)整個代碼和快排一樣,就是多了一個下標(biāo)位置的判斷,if (K - 1 == pointKey),這是核心,也就是為什么復(fù)雜度為NlogK。如果看不懂,可以先去理解快排的實(shí)現(xiàn)。

堆排序?qū)崿F(xiàn)TopK:

/**
 * 使用堆排序?qū)崿F(xiàn)的TopK問題 Title: Description: Company:
 * 
 * @author 鄭偉
 * @date 2018年4月11日上午9:28:15
 */
public class TopK_HeapSort {

  public static void main(String[] args) {
    int[] num = { 2, 20, 3, 7, 9, 1, 17, 18, 0, 4 };
    heapSort(num,3);
    System.out.println(Arrays.toString(num));
  }

  /**
   * 堆排序
   * 
   * @param num
   */
  private static void heapSort(int[] num, int K) {
    for (int i = num.length / 2 - 1; i >= 0; i--) {
      adjustMin(num, i, num.length);// 調(diào)整0~num.length-1的數(shù)據(jù)
    }
    // 如果要實(shí)現(xiàn)topK,就在這里執(zhí)行
    for (int j = num.length - 1; j >= 0 && K > 0; j--,K--) {
      // 交換最后一個
      swap(num, 0, j);
      // 再次調(diào)整0~j-1的數(shù)據(jù)
      adjustMin(num, 0, j);
    }
    //使用最大堆,K=3,輸出[9, 7, 3, 2, 4, 1, 0, 17, 18, 20],最大的三個值17,18,20
    //使用最小堆,K=3,輸出[3, 4, 9, 7, 20, 18, 17, 2, 1, 0],最小的三個值2,1,0
  }

  /**
   * 交換棧頂和最后一個元素
   * 
   * @param num
   * @param i
   * @param j
   */
  private static void swap(int[] num, int i, int j) {
    int tem = num[i];
    num[i] = num[j];
    num[j] = tem;
  }

  /**
   * 調(diào)整為大頂堆
   * 
   * @param num
   * @param root_index
   */
  private static void adjust(int[] num, int root_index, int length) {
    //
    int root = num[root_index];
    for (int j = root_index * 2 + 1; j < length; j = j * 2 + 1) {
      // 最大的兒子
      if (j + 1 < length && num[j] < num[j + 1]) {
        j = j + 1;// 指向了最大的兒子
      }
      if (root < num[j]) {
        num[root_index] = num[j];
        root_index = j;// 標(biāo)記換了哪一個位置
      } else {
        break;// 已經(jīng)是大頂堆了,不需要調(diào)整了
      }
    }
    num[root_index] = root;
  }

  /**
   * 小頂堆
   * 
   * @param num
   * @param root_index
   * @param length
   */
  private static void adjustMin(int[] num, int root_index, int length) {
    //
    int rootValue = num[root_index];
    for (int k = root_index * 2 + 1; k < length; k = k * 2 + 1) {
      if (k + 1 < length && num[k] > num[k + 1])
        k = k + 1;// K指向最小的子節(jié)點(diǎn)
      if (num[k] < rootValue) {
        num[root_index] = num[k];
        root_index = k;// 和k換了一下位置
      } else {
        break;// 本身不需要再調(diào)整了
      }
    }
    num[root_index] = rootValue;
  }
}

算法核心思想:與一般的堆排序不同的是,TopK只需要堆尾與堆頂交換K次就好,不需要全部交換一遍。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 使用idea創(chuàng)建web框架和配置struts的方法詳解

    使用idea創(chuàng)建web框架和配置struts的方法詳解

    這篇文章主要介紹了使用idea創(chuàng)建web框架和配置struts的方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-09-09
  • RocketMQ生產(chǎn)消息與消費(fèi)消息超詳細(xì)講解

    RocketMQ生產(chǎn)消息與消費(fèi)消息超詳細(xì)講解

    這篇文章主要介紹了RocketMQ生產(chǎn)消息與消費(fèi)消息,RocketMQ可用于以三種方式發(fā)送消息:可靠的同步、可靠的異步和單向傳輸。前兩種消息類型是可靠的,因?yàn)闊o論它們是否成功發(fā)送都有響應(yīng)
    2022-12-12
  • IDEA自動生成類圖和時序圖的操作指南

    IDEA自動生成類圖和時序圖的操作指南

    idea 的強(qiáng)大之處在于此,它包含了很多小插件,我們不需要再次下載相關(guān)插件,只需要在idea中小小的設(shè)置一下就可以了,本文我介紹了IDEA自動生成類圖和時序圖的操作指南,我用的是idea2020版本,需要的朋友可以參考下
    2024-05-05
  • Java實(shí)現(xiàn)讀取不同格式的文件的示例詳解

    Java實(shí)現(xiàn)讀取不同格式的文件的示例詳解

    在?Java?開發(fā)中,我們經(jīng)常需要讀取不同類型的文件,包括?Excel?表格文件、"doc"?等,本文將介紹如何使用?Java?讀取這些不同類型的文件,需要的可以參考下
    2024-01-01
  • 詳解spring+springmvc+mybatis整合注解

    詳解spring+springmvc+mybatis整合注解

    本篇文章主要介紹了詳解spring+springmvc+mybatis整合注解,詳細(xì)的介紹了ssm框架的使用,具有一定的參考價值,有興趣的可以了解一下
    2017-04-04
  • java日期操作工具類(獲取指定日期、日期轉(zhuǎn)換、相隔天數(shù))

    java日期操作工具類(獲取指定日期、日期轉(zhuǎn)換、相隔天數(shù))

    這篇文章主要為大家詳細(xì)介紹了java日期操作工具類,包括獲取指定日期、日期轉(zhuǎn)換、相隔天數(shù)等操作,感興趣的小伙伴們可以參考一下
    2016-06-06
  • 詳解Java內(nèi)部類與對象的打印概念和流程

    詳解Java內(nèi)部類與對象的打印概念和流程

    在 Java 中,可以將一個類定義在另一個類里面或者一個方法里面,這樣的類稱為內(nèi)部類。廣泛意義上的內(nèi)部類一般來說包括這四種:成員內(nèi)部類、局部內(nèi)部類、匿名內(nèi)部類和靜態(tài)內(nèi)部類
    2021-10-10
  • java實(shí)現(xiàn)文件和base64相互轉(zhuǎn)換

    java實(shí)現(xiàn)文件和base64相互轉(zhuǎn)換

    這篇文章主要為大家詳細(xì)介紹了java如何實(shí)現(xiàn)文件和base64相互轉(zhuǎn)換,文中的示例代碼講解詳細(xì),具有一定的參考價值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-11-11
  • MyBatis insert語句返回主鍵和selectKey標(biāo)簽方式

    MyBatis insert語句返回主鍵和selectKey標(biāo)簽方式

    這篇文章主要介紹了MyBatis insert語句返回主鍵和selectKey標(biāo)簽方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • 淺談springboot自動裝配原理

    淺談springboot自動裝配原理

    作為Spring Boot的精髓,自動配置原理首當(dāng)其沖.今天就帶大家了解一下springboot自動裝配的原理,文中有非常詳細(xì)的代碼示例,對正在學(xué)習(xí)java的小伙伴們很有幫助,需要的朋友可以參考下
    2021-05-05

最新評論