Leetcode 题解 - 排序

快速选择

用于求解 Kth Element 问题,使用快速排序的 partition() 进行实现。

需要先打乱数组,否则最坏情况下时间复杂度为 O(N2)。

堆排序

用于求解 TopK Elements 问题,通过维护一个大小为 K 的堆,堆中的元素就是 TopK Elements。

堆排序也可以用于求解 Kth Element 问题,堆顶元素就是 Kth Element。

快速选择也可以求解 TopK Elements 问题,因为找到 Kth Element 之后,再遍历一次数组,所有小于等于 Kth Element 的元素都是 TopK Elements。

可以看到,快速选择和堆排序都可以求解 Kth Element 和 TopK Elements 问题。

Kth Element

215. Kth Largest Element in an Array (Medium)

题目描述:找到第 k 大的元素。

排序 :时间复杂度 O(NlogN),空间复杂度 O(1)

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

堆排序 :时间复杂度 O(NlogK),空间复杂度 O(K)。

public int findKthLargest(int[] nums, int k) {
    PriorityQueue<Integer> pq = new PriorityQueue<>(); // 小顶堆
    for (int val : nums) {
        pq.add(val);
        if (pq.size() > k)  // 维护堆的大小为 K
            pq.poll();
    }
    return pq.peek();
}

快速选择 :时间复杂度 O(N),空间复杂度 O(1)

public int findKthLargest(int[] nums, int k) {
    k = nums.length - k;
    int l = 0, h = nums.length - 1;
    while (l < h) {
        int j = partition(nums, l, h);
        if (j == k) {
            break;
        } else if (j < k) {
            l = j + 1;
        } else {
            h = j - 1;
        }
    }
    return nums[k];
}

private int partition(int[] a, int l, int h) {
    int i = l, j = h + 1;
    while (true) {
        while (a[++i] < a[l] && i < h) ;
        while (a[--j] > a[l] && j > l) ;
        if (i >= j) {
            break;
        }
        swap(a, i, j);
    }
    swap(a, l, j);
    return j;
}

private void swap(int[] a, int i, int j) {
    int t = a[i];
    a[i] = a[j];
    a[j] = t;
}

桶排序

出现频率最多的 k 个数

347. Top K Frequent Elements (Medium)

Given [1,1,1,2,2,3] and k = 2, return [1,2].

设置若干个桶,每个桶存储出现频率相同的数,并且桶的下标代表桶中数出现的频率,即第 i 个桶中存储的数出现的频率为 i。

把数都放到桶之后,从后向前遍历桶,最先得到的 k 个数就是出现频率最多的的 k 个数。

public List<Integer> topKFrequent(int[] nums, int k) {
    Map<Integer, Integer> frequencyForNum = new HashMap<>();
    for (int num : nums) {
        frequencyForNum.put(num, frequencyForNum.getOrDefault(num, 0) + 1);
    }
    List<Integer>[] buckets = new ArrayList[nums.length + 1];
    for (int key : frequencyForNum.keySet()) {
        int frequency = frequencyForNum.get(key);
        if (buckets[frequency] == null) {
            buckets[frequency] = new ArrayList<>();
        }
        buckets[frequency].add(key);
    }
    List<Integer> topK = new ArrayList<>();
    for (int i = buckets.length - 1; i >= 0 && topK.size() < k; i--) {
        if (buckets[i] == null) {
            continue;
        }
        if (buckets[i].size() <= (k - topK.size())) {
            topK.addAll(buckets[i]);
        } else {
            topK.addAll(buckets[i].subList(0, k - topK.size()));
        }
    }
    return topK;
}

按照字符出现次数对字符串排序

451. Sort Characters By Frequency (Medium)

Input:
"tree"

Output:
"eert"

Explanation:
'e' appears twice while 'r' and 't' both appear once.
So 'e' must appear before both 'r' and 't'. Therefore "eetr" is also a valid answer.
public String frequencySort(String s) {
    Map<Character, Integer> frequencyForNum = new HashMap<>();
    for (char c : s.toCharArray())
        frequencyForNum.put(c, frequencyForNum.getOrDefault(c, 0) + 1);

    List<Character>[] frequencyBucket = new ArrayList[s.length() + 1];
    for (char c : frequencyForNum.keySet()) {
        int f = frequencyForNum.get(c);
        if (frequencyBucket[f] == null) {
            frequencyBucket[f] = new ArrayList<>();
        }
        frequencyBucket[f].add(c);
    }
    StringBuilder str = new StringBuilder();
    for (int i = frequencyBucket.length - 1; i >= 0; i--) {
        if (frequencyBucket[i] == null) {
            continue;
        }
        for (char c : frequencyBucket[i]) {
            for (int j = 0; j < i; j++) {
                str.append(c);
            }
        }
    }
    return str.toString();
}

荷兰国旗问题

荷兰国旗包含三种颜色:红、白、蓝。

有三种颜色的球,算法的目标是将这三种球按颜色顺序正确地排列。

它其实是三向切分快速排序的一种变种,在三向切分快速排序中,每次切分都将数组分成三个区间:小于切分元素、等于切分元素、大于切分元素,而该算法是将数组分成三个区间:等于红色、等于白色、等于蓝色。

按颜色进行排序

75. Sort Colors (Medium)

Input: [2,0,2,1,1,0]
Output: [0,0,1,1,2,2]

题目描述:只有 0/1/2 三种颜色。

public void sortColors(int[] nums) {
    int zero = -1, one = 0, two = nums.length;
    while (one < two) {
        if (nums[one] == 0) {
            swap(nums, ++zero, one++);
        } else if (nums[one] == 2) {
            swap(nums, --two, one);
        } else {
            ++one;
        }
    }
}

private void swap(int[] nums, int i, int j) {
    int t = nums[i];
    nums[i] = nums[j];
    nums[j] = t;
}

热门文章

暂无图片
编程学习 ·

DAY3-JDBC+Tomcat实现简易登陆系统

目录笔记bean包下User类dao包下UserDao类service包下UserServiceImpl类和UserService接口servlet包下HelloServlet类和LoginServlet类util包下DBUtil类xml文件 笔记 jdbc: 1.加载驱动 2.创建连接 3.写sq| 4.得到statement对象 5.执行sq|得到结果集 6.处理结果集 7.关闭资源 分…
暂无图片
编程学习 ·

一文读懂BERT(原理篇)

一文读懂BERT(原理篇)2018年的10月11日,Google发布的论文《Pre-training of Deep Bidirectional Transformers for Language Understanding》,成功在 11 项 NLP 任务中取得 state of the art 的结果,赢得自然语言处理学界的一片赞誉之声。本文是对近期关于BERT论文、相关文…
暂无图片
编程学习 ·

RabbitMQ 教程

RabbitMQ 教程 文章目录RabbitMQ 教程消息中间件安装及管理windows安装:RabbitMQLinux安装Mac安装基本概念主要概念Exchange的类型RabbitMQ的工作模式及代码示例简单模式 Simple2.工作模式 work (资源竞争消费)3.发布订阅 publish/subscribe (广播)4.路由 routing5.主题订阅…
暂无图片
编程学习 ·

Docker 进阶篇(一)镜像加速器,镜像管理,私有镜像仓库

Docker 进阶篇(一)镜像加速器,镜像管理,私有镜像仓库为Docker 设置存储空间配置镜像加速器镜像管理使用离线镜像搜索镜像通过容器创建对象将本地镜像推送到公网Docker 镜像仓库中创建Docker Register 私有仓库 为Docker 设置存储空间 在使用Docker的时候,经常会遇到Docker…
暂无图片
编程学习 ·

[46]api接口文档的生成和与项目文档进行集成

导出api文档 登录Eolinker 平台,生成api文档因为我们不是付费用户,所以无法导出markdown文档,所以导出了html文档 集成到docsify 因为docsify默认时处理markdown的,所以如果我们放上一个html文件就会出现解析错误,所以我们需要对该路径启用不处理window.$docsify = {name:…
暂无图片
郑州普通话 ·

学习笔记六——循环神经网络

一、RNN 前馈神经网络&#xff1a;信息往一个方向流动。包括MLP和CNN 循环神经网络&#xff1a;信息循环流动&#xff0c;网络隐含层输出又作为自身输入&#xff0c;包括RNN、LSTM、GAN等。 RNN模型结构如下图所示&#xff1a; 展开之后相当于堆叠多个共享隐含层参数的前馈…
暂无图片
代理记账 ·

学习笔记六——循环神经网络

一、RNN 前馈神经网络&#xff1a;信息往一个方向流动。包括MLP和CNN 循环神经网络&#xff1a;信息循环流动&#xff0c;网络隐含层输出又作为自身输入&#xff0c;包括RNN、LSTM、GAN等。 RNN模型结构如下图所示&#xff1a; 展开之后相当于堆叠多个共享隐含层参数的前馈…
暂无图片
cgfy ·

学习笔记六——循环神经网络

一、RNN 前馈神经网络&#xff1a;信息往一个方向流动。包括MLP和CNN 循环神经网络&#xff1a;信息循环流动&#xff0c;网络隐含层输出又作为自身输入&#xff0c;包括RNN、LSTM、GAN等。 RNN模型结构如下图所示&#xff1a; 展开之后相当于堆叠多个共享隐含层参数的前馈…
暂无图片
coreui ·

Heap Sort 讲解

Heap Sort sorts a group of unordered elements using the Heap data structure. The sorting algorithm using a Min Heap is as follows: Heapify all elements into a Min HeapRecord and delete the top elementPut to top element into an array T that stores all so
暂无图片
未来博客 ·

Heap Sort 讲解

Heap Sort sorts a group of unordered elements using the Heap data structure. The sorting algorithm using a Min Heap is as follows: Heapify all elements into a Min HeapRecord and delete the top elementPut to top element into an array T that stores all so
暂无图片
建站日记 ·

[react] 你觉得react上手快不快?它有哪些限制?

[react] 你觉得react上手快不快&#xff1f;它有哪些限制&#xff1f; 相对vue来说不快。 限制 需要学习JSX需要工程化的配置需要对原生JavaScript有相当的掌握react只是一个UI层面的库&#xff0c;像vue内置了动画处理、keep-alive等功能&#xff0c;react则需要去找第三方库…
暂无图片
mfbz ·

学习笔记六——循环神经网络

一、RNN 前馈神经网络&#xff1a;信息往一个方向流动。包括MLP和CNN 循环神经网络&#xff1a;信息循环流动&#xff0c;网络隐含层输出又作为自身输入&#xff0c;包括RNN、LSTM、GAN等。 RNN模型结构如下图所示&#xff1a; 展开之后相当于堆叠多个共享隐含层参数的前馈…
暂无图片
mfbz ·

AOV网是否存在回路-拓扑排序-C++

拓扑排序是对测试AOV网是否存在回路的方法&#xff01; 拓扑排序的过程中&#xff0c;由于需要查找所有以某顶点为尾的弧&#xff0c;即找到该顶点的所有出边&#xff0c;故图要采用邻接表的存储方式。但拓扑排序较邻接表的存储方式有一点不同&#xff0c;由于要查找入度为0的点…
暂无图片
珊珊日记 ·

学习笔记六——循环神经网络

一、RNN 前馈神经网络&#xff1a;信息往一个方向流动。包括MLP和CNN 循环神经网络&#xff1a;信息循环流动&#xff0c;网络隐含层输出又作为自身输入&#xff0c;包括RNN、LSTM、GAN等。 RNN模型结构如下图所示&#xff1a; 展开之后相当于堆叠多个共享隐含层参数的前馈…
暂无图片
珊珊日记 ·

AOV网是否存在回路-拓扑排序-C++

拓扑排序是对测试AOV网是否存在回路的方法&#xff01; 拓扑排序的过程中&#xff0c;由于需要查找所有以某顶点为尾的弧&#xff0c;即找到该顶点的所有出边&#xff0c;故图要采用邻接表的存储方式。但拓扑排序较邻接表的存储方式有一点不同&#xff0c;由于要查找入度为0的点…