Top K问题

1、题目

给定一个长度为 N N N 的无序数组 a r r arr a rr,和一个正数 k ( k ≤ N ) k(k \le N)k (k ≤N ),返回前 k k k 个最大的数,即 Top k k k。

使用下列 3 个不同复杂度的三个方法实现:

1)O ( N ∗ l o g N ) O(N logN)O (N ∗l o g N )
2)O ( N + k ∗ l o g N ) O(N + k
logN)O (N +k ∗l o g N )
3)O ( N + k ∗ l o g k ) O(N + k * logk)O (N +k ∗l o g k )

2、思路

对原数组进行从小到大排序,排好序后从右往左取出 k k k 个数即可。

public class MaxTopK {

    public static int[] maxTopK1(int[] arr, int k) {
        if (arr == null || arr.length == 0) {
            return new int[0];
        }
        int N = arr.length;
        k = Math.min(N, k);
        Arrays.sort(arr);
        int[] ans = new int[k];
        for (int i = N - 1, j = 0; j < k; i--, j++) {
            ans[j] = arr[i];
        }
        return ans;
    }
}

无序数组从下向上建大根堆的时间复杂度 O ( N ) O(N)O (N ),然后从堆中弹出 k k k 个数,而每次弹出堆顶后调整堆的时间复杂度为 O ( l o g N ) O(logN)O (l o g N ),所以弹出 k k k 个数的时间复杂度为 O ( k ∗ l o g N ) O(k*logN)O (k ∗l o g N ),因此总的时间复杂度为 O ( N + k ∗ l o g N ) O(N + k * logN)O (N +k ∗l o g N )。

public class MaxTopK {

    public static int[] maxTopK2(int[] arr, int k) {
        if (arr == null || arr.length == 0) {
            return new int[0];
        }
        int N = arr.length;
        k = Math.min(N, k);

        for (int i = N - 1; i >= 0; i--) {
            heapify(arr, i, N);
        }

        int heapSize = N;
        swap(arr, 0, --heapSize);
        int count = 1;
        while (heapSize > 0 && count < k) {
            heapify(arr, 0, heapSize);
            swap(arr, 0, --heapSize);
            count++;
        }
        int[] ans = new int[k];
        for (int i = N - 1, j = 0; j < k; i--, j++) {
            ans[j] = arr[i];
        }
        return ans;
    }

    public static void heapInsert(int[] arr, int index) {
        while (arr[index] > arr[(index - 1) / 2]) {
            swap(arr, index, (index - 1) / 2);
            index = (index - 1) / 2;
        }
    }

    public static void heapify(int[] arr, int index, int heapSize) {
        int left = index * 2 + 1;
        while (left < heapSize) {
            int largest = left + 1 < heapSize && arr[left + 1] > arr[left] ? left + 1 : left;
            largest = arr[largest] > arr[index] ? largest : index;
            if (largest == index) {
                break;
            }
            swap(arr, largest, index);
            index = largest;
            left = index * 2 + 1;
        }
    }

    public static void swap(int[] arr, int i, int j) {
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }
}

要求N N N个数中前 k k k 大的数,可以使用 改造快排或bfprt算法 先求出第 N − k N – k N −k 小的数 m m m(即第k k k大的数),时间复杂度 O ( N ) O(N)O (N );

然后准备一个长度为 k k k 的数组,遍历一遍数组,只要数比 m m m 大就收集,假设收集到大于 m m m 的数有 x ( x < k ) x(x < k)x (x <k ) 个,那么剩下的 k − x k – x k −x 个毫无疑问都是 m m m,这个过程的时间复杂度为 O ( N ) O(N)O (N );

最后,因为结果要求是有序的,所以对这个长度为 k k k 的数组进行排序,时间复杂度 O ( k ∗ l o g k ) O(k*logk)O (k ∗l o g k )。

因此,总的时间复杂度为 O ( N + k ∗ l o g k ) O(N + k *logk)O (N +k ∗l o g k )。

public class MaxTopK {

    public static int[] maxTopK3(int[] arr, int k) {
        if (arr == null || arr.length == 0) {
            return new int[0];
        }
        int N = arr.length;
        k = Math.min(N, k);

        int num = minKth(arr, N - k);
        int[] ans = new int[k];
        int index = 0;
        for (int i = 0; i < N; i++) {
            if (arr[i] > num) {
                ans[index++] = arr[i];
            }
        }
        for (; index < k; index++) {
            ans[index] = num;
        }

        Arrays.sort(ans);
        for (int L = 0, R = k - 1; L < R; L++, R--) {
            swap(ans, L, R);
        }
        return ans;
    }

    public static int minKth(int[] arr, int index) {
        int L = 0;
        int R = arr.length - 1;
        int pivot = 0;
        int[] range = null;
        while (L < R) {
            pivot = arr[L + (int) (Math.random() * (R - L + 1))];
            range = partition(arr, L, R, pivot);
            if (index < range[0]) {
                R = range[0] - 1;
            } else if (index > range[1]) {
                L = range[1] + 1;
            } else {
                return pivot;
            }
        }
        return arr[L];
    }

    public static int[] partition(int[] arr, int L, int R, int pivot) {
        int less = L - 1;
        int more = R + 1;
        int cur = L;
        while (cur < more) {
            if (arr[cur] < pivot) {
                swap(arr, ++less, cur++);
            } else if (arr[cur] > pivot) {
                swap(arr, cur, --more);
            } else {
                cur++;
            }
        }
        return new int[] { less + 1, more - 1 };
    }

    public static void swap(int[] arr, int i, int j) {
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }
}
public class MaxTopK {

    public static int[] generateRandomArray(int maxSize, int maxValue) {
        int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
        for (int i = 0; i < arr.length; i++) {

            arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
        }
        return arr;
    }

    public static int[] copyArray(int[] arr) {
        if (arr == null) {
            return null;
        }
        int[] res = new int[arr.length];
        for (int i = 0; i < arr.length; i++) {
            res[i] = arr[i];
        }
        return res;
    }

    public static boolean isEqual(int[] arr1, int[] arr2) {
        if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {
            return false;
        }
        if (arr1 == null && arr2 == null) {
            return true;
        }
        if (arr1.length != arr2.length) {
            return false;
        }
        for (int i = 0; i < arr1.length; i++) {
            if (arr1[i] != arr2[i]) {
                return false;
            }
        }
        return true;
    }

    public static void printArray(int[] arr) {
        if (arr == null) {
            return;
        }
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        int testTime = 500000;
        int maxSize = 100;
        int maxValue = 100;
        boolean pass = true;
        System.out.println("测试开始,没有打印出错信息说明测试通过");
        for (int i = 0; i < testTime; i++) {
            int k = (int) (Math.random() * maxSize) + 1;
            int[] arr = generateRandomArray(maxSize, maxValue);

            int[] arr1 = copyArray(arr);
            int[] arr2 = copyArray(arr);
            int[] arr3 = copyArray(arr);

            int[] ans1 = maxTopK1(arr1, k);
            int[] ans2 = maxTopK2(arr2, k);
            int[] ans3 = maxTopK3(arr3, k);
            if (!isEqual(ans1, ans2) || !isEqual(ans1, ans3)) {
                pass = false;
                System.out.println("出错了!");
                printArray(ans1);
                printArray(ans2);
                printArray(ans3);
                break;
            }
        }
        System.out.println("测试结束了,测试了" + testTime + "组,是否所有测试用例都通过?" + (pass ? "是" : "否"));
    }

}

因为 k ≤ N k \le N k ≤N,所以方法三 O ( N + k ∗ l o g k ) O(N+k*logk)O (N +k ∗l o g k ) 最可能是最优解。

Original: https://blog.csdn.net/u011386173/article/details/128430093
Author: 明朗晨光
Title: Top K问题

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/787518/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • python基本数据类型

    python的变量不需要声明,但在使用前必须要赋值 多个变量赋值: python有六个标准的数据类型: Number、String、Tuple、List、Set、Dictionar…

    Python 2023年11月3日
    026
  • Python伪代码分析点赞器实现原理

    Original: https://www.cnblogs.com/123456feng/p/16179283.htmlAuthor: 蚂蚁ailingTitle: Python伪…

    Python 2023年11月3日
    039
  • macOS conda 安装指定版本的 Pytorch

    因为在 macOS 下用不了 CUDA, 所以安装 Pytorch 时只能安装 CPU 版本的. 此外, 按照 Pytorch 官网给出的安装方式, 网络太慢了, 并且总是中断, …

    Python 2023年9月9日
    041
  • 机器学习——线性回归案例——波士顿房价预测

    因为此案例比较经典,所以数据已经镶嵌在里面了 1、导入模块。 模型获取,有线性回归、岭回归、套索回归模型 from sklearn.linear_model import Line…

    Python 2023年8月1日
    068
  • PYTHON

    个人运用python软件编程”飞机大战”程序。让”飞机大战”程序无bug的运行。过程步骤:1. 查阅并搜集python的相关资料。2…

    Python 2023年9月25日
    024
  • 自动驾驶——自动泊车之平行泊车位学习

    抵扣说明: 1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。 Original: https://blo…

    Python 2023年11月8日
    036
  • inx函数python_Python数据分析入门

    如今数据分析越来越重要,比起使用excel等工具,使用编程语言更加高效。这篇文章主要介绍一些简单的数据分析入门知识,使用的语言是python。 读取csv文件 数据分析的第一步是要…

    Python 2023年8月18日
    067
  • Python NLP入门教程

    本文简要介绍Python自然语言处理(NLP),使用Python的NLTK库。NLTK是Python的自然语言处理工具包,在NLP领域中,最常使用的一个Python库。 什么是NL…

    Python 2023年6月3日
    063
  • 【工程伦理】脑机接口技术中的伦理问题分析

    目录 1、引言 2、主要伦理问题讨论 参考文献 1、脑机接口技术介绍 脑机接口_百度百科脑机接口 (Brain Computer Interface,BCI [4] ),指在人或动…

    Python 2023年9月15日
    084
  • 【深度强化学习】多智能体算法汇总

    0 Preliminaries 在多智能体强化学习算法中,两个主要的技术指标为合理性与收敛性。 合理性(rationality):在对手使用一个恒定策略的情况下,当前智能体能够学习…

    Python 2023年9月27日
    042
  • 爬虫与反爬虫技术简介

    vivo 互联网安全团队- Xie Peng 互联网的大数据时代的来临,网络爬虫也成了互联网中一个重要行业,它是一种自动获取网页数据信息的爬虫程序,是网站搜索引擎的重要组成部分。通…

    Python 2023年10月21日
    036
  • Pytest框架详解(一)

    Pytest框架详解(一) 文章目录 Pytest框架详解(一) * 一、概述 二、安装与入门 – 1、快速上手 2、第一个测试 3、python代码调用pytest …

    Python 2023年9月11日
    074
  • Flask项目打开总是上一个项目的网页

    啊哦~你想找的内容离你而去了哦 内容不存在,可能为如下原因导致: ① 内容还在审核中 ② 内容以前存在,但是由于不符合新 的规定而被删除 ③ 内容地址错误 ④ 作者删除了内容。 可…

    Python 2023年8月9日
    065
  • 【Pandas】DataFrame只复制其中的某一行为多次

    import pandas as pd df = pd.DataFrame(data={ ‘id’: [‘1’, ‘2’, ‘3’], ‘col1’ : [ 5, 6, 7], ‘…

    Python 2023年8月18日
    040
  • Django配置与添加app

    uniapp 数据展示 Python + 数据库 = 管理系统 Django 框架 : WEB 开发框架 ,后台管理 pip : 包管理器,下载安装第三方组件使用的。 Python…

    Python 2023年8月9日
    055
  • Python实现定时自动关闭的tkinter窗口

    功能简要说明:程序运行后10秒钟自动关闭。 技术要点:tkinter应用程序的destroy()方法,多线程编程。 代码截图: 运行效果: 1、继《 Python程序设计基础》(2…

    Python 2023年9月23日
    047
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球